当前位置: 首页 > news >正文

Linux进程第十一讲——进程优先级的本质与Linux实现

Linux进程第十一讲——进程优先级的本质与Linux实现

上一篇我们理解了孤儿进程的领养机制与PCB的多结构组织,知道了进程会通过链表参与调度、通过树结构维护父子关系。但新的问题随之而来:当运行队列中有多个进程时,调度器该优先选择哪个进程执行?这就涉及到进程的核心属性——优先级(Priority)

优先级是Linux调度器实现“良性竞争”的关键:它决定了进程获取CPU资源的先后顺序,避免“强势进程独占资源”或“弱势进程长期饥饿”。本文将从优先级的基础概念入手,区分优先级与权限的本质差异,详解Linux中优先级的表示方式(PRI与NI),并通过实操让大家掌握优先级的查看方法。

一、优先级的基础:不是“能不能”,而是“谁先谁后”

在理解Linux的优先级实现前,我们需要先澄清一个核心误区:优先级与权限的区别。很多初学者会将两者混淆,但它们解决的是完全不同的问题。

1.1 优先级 vs 权限:两个维度的资源管理

我们可以用生活中的“食堂打饭”场景,清晰区分两者:

  • 权限(Permission):决定“你能不能进食堂”。比如食堂只对学校师生开放,校外人员没有权限进入——这是“资格”问题,要么能,要么不能;
  • 优先级(Priority):决定“你进食堂后谁先打饭”。比如老师窗口优先于学生窗口,或者学生排队时按先来后到顺序——这是“顺序”问题,在有资格的前提下,确定谁先获取资源。

对应到Linux系统中:

  • 权限:比如进程能否读写某个文件(rwx权限)、能否创建新进程(fork权限)、能否访问内核资源(root权限)——这些都是“资格”判断,没有权限则操作直接失败;
  • 优先级:比如两个进程都需要CPU资源(都有运行资格),优先级高的进程先获得时间片,优先级低的进程后获得——这是“顺序”判断,不影响“能不能运行”,只影响“什么时候运行”。

一句话总结:权限解决“资格”问题,优先级解决“顺序”问题

1.2 为什么需要优先级?资源有限下的“良性竞争”

优先级的存在,本质是因为系统资源是有限的,而进程是多的——CPU核心数(4核、8核)远少于进程数(可能上百个),磁盘IO、网络带宽等资源也同样有限。如果没有优先级,调度器只能“随机”或“轮询”调度,会导致两个严重问题:

问题1:关键进程响应缓慢

比如系统中的sshd(远程登录进程)、nginx(Web服务进程)是关键服务,若与后台的日志备份进程“平等竞争”CPU,可能导致用户登录卡顿、网页加载缓慢——这显然不符合用户需求。

问题2:进程饥饿(Starvation)

若所有进程轮流获取CPU时间片,某些低优先级进程可能长期得不到足够资源。比如一个后台数据分析进程,每次刚获得时间片就被高频率的前台进程(如浏览器、终端)抢占,导致数据分析几天都无法完成——这种“长期得不到推进”的现象,就是进程饥饿。

优先级的作用,就是通过“差异化分配资源”解决这些问题:

  • 给关键进程(如sshd、数据库)更高优先级,确保其快速响应;
  • 给后台进程(如日志备份、数据分析)更低优先级,让其在系统空闲时运行,避免影响前台体验;
  • 同时通过“优先级范围限制”,防止某个进程优先级过高而独占资源,保障整体调度公平。

1.3 生活中的优先级:理解调度的本质

其实我们生活中处处可见优先级的设计,这些场景与Linux调度逻辑高度相似:

  1. 医院急诊:急诊病人(高优先级)优先于普通门诊病人(低优先级),避免急诊病人因排队延误治疗——对应Linux中“紧急服务进程优先”;
  2. 交通路口:救护车、消防车(高优先级)优先通行,普通车辆(低优先级)避让——对应Linux中“内核进程优先于用户进程”;
  3. 电梯调度:电梯会优先响应“当前楼层附近的请求”(动态优先级调整),避免某个楼层的请求长期等待——对应Linux中“进程优先级可动态调整”。

这些场景的核心逻辑与Linux优先级一致:在资源有限的前提下,通过优先级实现“重要需求优先满足,次要需求错峰满足”,兼顾效率与公平

二、Linux中的优先级表示:PRI与NI的关系

Linux并没有直接让用户修改进程的“优先级数值”,而是通过两个字段间接管理:PRI(Priority,优先级)NI(Nice,修正值)。理解这两个字段的关系,是掌握Linux优先级的关键。

2.1 查看优先级:ps命令的PRI与NI字段

要观察进程的优先级,最常用的命令是ps -al(或ps axl),它会显示进程的PRI和NI字段。我们通过一个实验来查看:

步骤1:创建一个长期运行的进程

编写priority_demo.c,让进程进入死循环,方便观察:

#include <stdio.h>
#include <unistd.h>int main() {while (1) {printf("我是测试进程,PID: %d | 正在运行...\n", getpid());sleep(1);  // 每秒打印一次,避免占用过多CPU}return 0;
}

编译并运行:

gcc priority_demo.c -o priority_demo
./priority_demo &  # 后台运行,避免阻塞终端
步骤2:用ps命令查看优先级

执行ps -al | grep priority_demo,输出如下(关键字段已标注):

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000  1234  1232  0  80   0 -  2312 hrtime pts/0    00:00:00 priority_demo

其中:

  • PRI:当前进程的优先级数值,默认值为80;
  • NI:优先级修正值,默认值为0;
  • C:进程占用CPU的百分比(这里为0,因为进程大部分时间在sleep)。

2.2 核心公式:PRI与NI的换算关系

Linux中,进程的实际优先级(PRI)并非固定不变,而是由“基础PRI”和“NI修正值”共同决定,核心公式如下:

新PRI = 基础PRI + NI

其中:

  • 基础PRI:默认值为80(不同Linux发行版可能略有差异,但原理一致);
  • NI(Nice值):用户可调整的修正值,范围为[-20, 19](共40个等级)。

根据这个公式,我们可以推导出NI对优先级的影响:

  1. NI为负数:新PRI = 80 + 负数 → PRI变小,优先级变高。例如NI=-5时,PRI=75,进程更容易被调度;
  2. NI为0:新PRI=80,默认优先级;
  3. NI为正数:新PRI = 80 + 正数 → PRI变大,优先级变低。例如NI=10时,PRI=90,进程更难被调度。

这里有一个关键规则:PRI值越小,优先级越高。这与我们直觉中的“数值越大优先级越高”相反,需要特别注意。

2.3 为什么限制NI范围为[-20, 19]?保障调度公平

有同学可能会问:为什么不让NI的范围更大?比如设置NI=-100,让PRI=80-100=-20,让进程优先级极高,独占CPU资源。

答案是:为了避免优先级失控,保障调度公平。Linux调度器的核心目标是“让所有进程都能获得合理的CPU时间”,若允许NI无限制调整,会导致:

  • 高优先级进程长期独占CPU,低优先级进程陷入饥饿;
  • 用户可能通过设置极高优先级的进程,抢占系统关键服务(如initsshd)的资源,导致系统崩溃。

因此,Linux内核将NI的范围严格限制在[-20, 19],这意味着:

  • 最高优先级:NI=-20 → PRI=80-20=60;
  • 最低优先级:NI=19 → PRI=80+19=99;
  • 所有普通进程的优先级都在60~99之间,不会出现极端的优先级差异,既满足了“差异化调度”的需求,又保障了“整体公平”。

2.4 优先级与时间片的关系:高优先级进程获得更多资源

优先级的最终作用,体现在“时间片分配”上。Linux的调度器(如CFS,完全公平调度器)会根据进程的PRI值,分配不同长度的时间片:

  • 高优先级进程(PRI小):获得更长的时间片。例如PRI=60的进程,每次可能获得100ms的时间片;
  • 低优先级进程(PRI大):获得更短的时间片。例如PRI=99的进程,每次可能获得10ms的时间片。

这种分配方式的逻辑是:重要的进程需要更多时间完成任务,次要的进程在空闲时运行即可。比如数据库进程(高优先级)需要长时间处理查询,而日志备份进程(低优先级)可以分多次、短时间运行,不影响其他服务。

三、优先级的实际意义:为什么普通用户很少调整?

很多初学者会觉得“调整优先级可以大幅提升程序性能”,但在实际工作中,普通用户或开发者很少手动调整进程优先级。这背后有两个核心原因:

3.1 Linux调度器已足够智能

现代Linux内核使用的CFS(完全公平调度器),会根据进程的“实际需求”动态调整优先级:

  • 若进程是CPU密集型(如数据分析),调度器会适当降低其优先级,避免独占CPU;
  • 若进程是IO密集型(如数据库、Web服务),调度器会适当提高其优先级,确保其快速响应IO请求;
  • 即使不手动调整NI,调度器也能根据进程行为,实现“按需分配”的优先级管理。

例如,当你运行一个后台编译程序(CPU密集型)和一个浏览器(IO密集型)时,CFS会自动给浏览器更高优先级,确保你浏览网页时不卡顿,同时让编译程序在CPU空闲时推进——这种动态调整比手动设置NI更精准。

3.2 不当调整可能引发风险

手动调整优先级若操作不当,反而会导致系统问题:

  • 案例1:将普通应用(如播放器)的NI设为-20(最高优先级),可能抢占sshd的资源,导致远程登录卡顿;
  • 案例2:将后台备份进程的NI设为19(最低优先级),可能导致备份任务几天都无法完成,错过备份窗口;
  • 案例3:非root用户无法设置NI为负数(Linux权限限制),若普通用户能随意提高优先级,会引发权限安全问题。

因此,只有在特定场景下(如服务器优化、实时任务处理),才需要由管理员手动调整优先级,且调整前需充分评估对系统的影响。

四、总结:优先级的核心认知与后续铺垫

通过本文的讲解,我们可以总结出Linux进程优先级的核心知识点:

  1. 优先级的本质:解决“资源顺序分配”问题,与“权限(资格)”完全不同;
  2. Linux的表示方式:通过PRI(优先级数值)和NI(修正值)管理,核心公式为新PRI=80+NI,NI范围[-20,19]
  3. 调度逻辑:PRI越小优先级越高,获得更长时间片,兼顾效率与公平;
  4. 实际使用:调度器已动态优化优先级,普通用户无需手动调整,避免引发风险。

理解了优先级,我们自然会思考:如何手动调整进程的优先级?Linux提供了nice(启动时设置)和renice(运行时调整)两个命令,以及top命令的交互调整方式。下一篇,我们将聚焦于这些实操工具,详细讲解优先级调整的步骤、注意事项,以及内核调度器的底层实现逻辑,让大家不仅“知其然”,更“知其所以然”。

感谢大家的关注,我们下期再见!
丰收的田野

http://www.dtcms.com/a/469761.html

相关文章:

  • Java Redis “持久化”面试清单(含超通俗生活案例与深度理解)
  • Linux一切皆文件的意义
  • 网站怎样建立数据库连接做网站公司职员工资
  • 【javascript】js使用技巧笔记
  • 复现嘉立创小项目之直流稳压电源
  • Kubernetes 之海,Go 之舟:避开那些吞噬性能的隐形暗礁
  • 基于独立成分分析(ICA)的图像分离技术实现
  • 网站建站如何做seo有免费的网站服务器吗
  • 使用LangChain创建智能Agent完整指南
  • 江苏省网站备案电话怎样做网站开发
  • Qt:窗口与文件绑定
  • git常用命令大全
  • 算法 - 递归
  • 软考-系统架构设计师 系统架构评估详细讲解
  • Redis 黑马skyout
  • 【Unity】构建超实用的有限状态机管理类
  • redis基础命令和深入理解底层
  • Java中第三方报告库-Allure
  • 高端公司网站建设连云港做网站制作
  • Google 智能体设计模式:优先级排序
  • 网站做不做百度云加速手游代理平台哪个好
  • 【国内电子数据取证厂商龙信科技】邮件如何取证?
  • 手机网站模板 psd做网站建设分哪些类型
  • 做网站需要哪些框架网站没备案可以访问吗
  • Git下载和安装教程(附安装包)
  • go的学习2---》并发编程
  • 高端网站建设企业公司网页版qq空间登录入口官网
  • 麒麟系统安装达梦数据库遇到的问题
  • VScode怎么使用Jupyter并且设置内核
  • LwIP UDP RAW