Re:Linux系统篇(二十)进程篇·五:深入理解 Linux 进程优先级:从底层逻辑到实战修改


◆ 博主名称: 小此方-CSDN博客 大家好,欢迎来到小此方的博客。
⭐️Linux系列个人专栏: 【主题曲】Linux
⭐️此方的GitHub: github_此方
⭐️ Re系列专栏:我们思考 (Rethink) · 我们重建 (Rebuild) · 我们记录 (Record)


文章目录

  • 概要&序論
  • 零、知识点
  • [一、 进程优先级的基本概念](#一、 进程优先级的基本概念)
    • [1.1 为什么要有进程优先级?](#1.1 为什么要有进程优先级?)
      • [1.1.1 资源稀缺性与排队机制](#1.1.1 资源稀缺性与排队机制)
      • [1.1.2 区分:优先级与权限](#1.1.2 区分:优先级与权限)
        • [1.1.2.1 UID(User ID)](#1.1.2.1 UID(User ID))
      • [1.1.3 进程优先级的正面作用](#1.1.3 进程优先级的正面作用)
    • [1.2 Linux 下查看进程优先级](#1.2 Linux 下查看进程优先级)
      • [1.2.1 使用ps -l命令查看](#1.2.1 使用ps -l命令查看)
      • [1.2.2 核心指标:PRI 与 NI](#1.2.2 核心指标:PRI 与 NI)
    • [1.3 进程优先级的计算公式](#1.3 进程优先级的计算公式)
      • [1.3.1 动态计算公式](#1.3.1 动态计算公式)
      • [1.3.2 Nice 值对最终优先级的映射](#1.3.2 Nice 值对最终优先级的映射)
    • [1.4 Nice 值的取值范围与限制原因](#1.4 Nice 值的取值范围与限制原因)
      • [1.4.1 Nice 值的取值范围](#1.4.1 Nice 值的取值范围)
      • [1.4.2 为什么要把 Nice 值的范围限制得这么小?](#1.4.2 为什么要把 Nice 值的范围限制得这么小?)
    • [1.5 优先级修改方法](#1.5 优先级修改方法)

概要&序論

Hello大家好我是此方 。在上一章中,我们彻底起底了僵尸进程与孤儿进程的底层逻辑。本期我们将突破 Linux 内核中一个至关重要的前置核心概念------进程优先级(Priority)

我们将从它存在的底层逻辑聊起,一路深入到 Linux 下的查看方法、核心计算公式、Nice 值的映射限制,再到最后的系统调用修改实战,帮助大家彻底看透操作系统调度的本质。好了,直接开始!

零、知识点

本文内容有点跳跃,在之前应该补充一些内容

0.1竞争、独立、并行、并发

0.1.1概念解释

  • 竞争性 :系统进程数目众多,而 CPU 资源只有少量,甚至 1 个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理地竞争相关资源,便有了优先级
  • 独立性 :多进程运行,需要独享各种资源,多进程运行期间互不干扰。
  • 并行 :多个进程在多个 CPU 下分别同时进行运行,这称之为并行。
  • 并发 :多个进程在一个 CPU 下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

0.1.2喝咖啡

并发(Concurrent) :咖啡店只有一台咖啡机(单核 CPU),前排了两条顾客长龙。咖啡师只能给 A 队做一杯,再转头给 B 队做一杯,通过高频无缝切换让两条队伍同时缓慢推进。虽然微观上某一时刻只能服务一个人,但宏观上两个队列都在向前推进。

并行(Parallel) :同一家咖啡店直接升级安装了两台一模一样的咖啡机(多核 CPU)。两位咖啡师各占一台机器,同时在同一时刻为两位顾客制作咖啡。两个队伍在各自的物理设备上独立、同时推进,互不干扰。

怎么查看你的机器是单核还是双核?指令:

bash 复制代码
cat etc/cpuinfo

0.2 基于时间片的分时操作系统

早期的计算机采用的是单任务批处理系统,一个程序不跑完,后面的程序只能干等着。而现代 Linux 则是典型的分时操作系统

0.2.1什么是时间片

内核为了让多个进程"看起来"是在同时运行的,会给运行队列中的每一个进程分配一段微小的 CPU 轮转执行时间,这个极其短暂的时间区域就叫做时间片(通常只有几毫秒到几十毫秒)。

0.2.2时间片轮转机制的好处

基于时间片轮转机制,Linux 的多任务运行呈现出一种独特的运行景观:

  • 微观串行: 在极短的几毫秒(一个时间片)内,CPU 核心依然是严格单线程、串行地只执行某一个进程的指令。
  • 宏观并行: 当一个进程的时间片耗尽,操作系统会立刻剥夺其 CPU 使用权,强行将其推回队列排队,并把 CPU 切换给下一个进程(这就是进程切换)。因为时间片极短且切换频率极高,在人类肉眼的宏观视觉下,就造成了所有程序都在同时流畅运行的"并行"错觉。

一、 进程优先级的基本概念

在多任务操作系统中,CPU 的资源是有限的,而需要运行的进程往往有很多。为了保证系统高效、有序地运行,操作系统必须有一套机制来决定"谁先运行,谁后运行",这就是进程优先级。

1.1 为什么要有进程优先级?

1.1.1 资源稀缺性与排队机制

进程优先级的存在,本质是因为CPU资源是稀缺的 。一个CPU核心在同一时刻只能处理一个进程的指令。

当系统中有大量进程同时维持在运行(R)状态时,它们就必须在运行队列中排队。优先级的高低,实际上就是决定在排队等待时,谁能够排在前面、谁能优先获得CPU的分配资源

1.1.2 区分:优先级与权限

很多初学者容易将"优先级"和"权限"搞混,它们在操作系统中是完全不同的概念:

  • 权限: 决定的是你能不能做某件事。例如,普通用户能否读取 root 权限的文件。
  • 优先级: 决定的是你先做还是后做某件事。它假设你已经具备了执行的权限,只是在时间节点上进行排队。
1.1.2.1 UID(User ID)

在 Linux 内核中,系统用来识别用户身份、划分进程归属的硬核判据并不是"用户名"这样的字符串,而是一串数字------UID(User ID,用户标识符)

  • 内核对身份的数字化绑定 :每当一个用户在终端启动一个程序时,内核在为其创建进程控制块(task_struct)时,会将该用户的 UID 直接写入其中。这意味着,系统中的每一个进程,底层都有那个UID数字。
  • UID 的划分规则
    • 0 :超级用户 root 的 UID 永远是 0最高权力
    • 1000+ :现代 Linux 发行版中,普通用户的 UID 通常从 1000 开始往后顺序累加(如 1000, 1001, 1002...)。
  • 如何查看 UID :在终端输入 ps -lps -al 命令,输出结果中包含的 UID 列对应的数字,代表的就是该进程的拥有者是谁

-n选项,以数字形式返回。 原本ll显示的是我们的用户名,这个用户名是被包装的。

那么回到我们的进程,我们为什么要突然插入uid的概念?访问一个文件,是什么去访问?进程去访问。进程访问进程怎么知道自己有没有能力去访问------看权限,权限来自哪里?来自UID,也就是用户。通了。

1.1.3 进程优先级的正面作用

合理配置和动态调整进程优先级,可以带来以下好处:

  • 改善系统性能: 让关键的系统核心服务(如中断处理、音视频流实时解码)优先运行,避免卡顿。
  • 提升用户体验: 交互式进程(如用户正在使用的窗口、鼠标键盘响应)会被赋予更高的优先级,使得系统反馈更加流畅、跟手。

在 Linux 的 O(1) 调度算法等底层设计中,优先级越高的进程,往往会被系统分配到更长、更充裕的时间片;而优先级较低的进程,分配到的时间片则相对较短。

1.2 Linux 下查看进程优先级

1.2.1 使用ps -l命令查看

在 Linux 终端中,我们可以通过输入 ps -l(或 ps -al实际上得加上这个a选项 )命令来查看当前终端下进程的详细列表和硬核指标。

输入命令后,输出的头部字段通常包含以下信息:

bash 复制代码
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000  3214  3200  0  80   0 - 29115 do_wai pts/0    0:00:00 bash
0 R  1000  3521  3214  0  80   0 - 38312 -      pts/0    0:00:00 ps

1.2.2 核心指标:PRI 与 NI

在输出的众多列中,我们需要重点关注两个与进程优先级直接相关的核心指标:PRINI

  • PRI(Priority,进程优先级): 这是进程真正被 CPU 执行时的最终优先级指标。
    • 数字越小,对应的优先级越高,意味着越先被 CPU 执行。
  • NI(Nice,谦让值/ nice 值):
    • 这是我们要手动或动态调整的修正数据。
    • 它表示进程的"谦让程度"。Nice 值越小(负数),说明该进程越不想谦让,想要抢占更多 CPU 资源,从而拉低 PRI;Nice 值越大(正数),说明它越谦让,愿意把资源让给别人。

这样设计的好处:修改优先级的时候不需要知道优先级历史上是多少。

1.3 进程优先级的计算公式

1.3.1 动态计算公式

在 Linux 系统中,进程最终的优先级 PRI 并不是一成不变的,而是由系统基准值与 Nice 值共同叠加计算出来的。
其核心计算公式如下:

P R I ( 最终 ) = P R I ( 基准 ) + N I PRI_{(最终)} = PRI_{(基准)} + NI PRI(最终)=PRI(基准)+NI

基准值是多少?

在标准 Linux 内核中,普通进程的默认基准优先级 P R I ( 基准 ) PRI_{(基准)} PRI(基准) 通常固定为 80

1.3.2 Nice 值对最终优先级的映射

通过公式我们可以非常直观地看出 Nice 值是如何干预进程优先级的:

  • 当 N I = 0 NI = 0 NI=0 时(默认状态): P R I ( 最终 ) = 80 + 0 = 80 PRI_{(最终)} = 80 + 0 = 80 PRI(最终)=80+0=80。
  • 当 N I = − 10 NI = -10 NI=−10 时(不想谦让): P R I ( 最终 ) = 80 + ( − 10 ) = 70 PRI_{(最终)} = 80 + (-10) = 70 PRI(最终)=80+(−10)=70。此时数字变小,优先级反而提升了
  • 当 N I = 15 NI = 15 NI=15 时(极度谦让): P R I ( 最终 ) = 80 + 15 = 95 PRI_{(最终)} = 80 + 15 = 95 PRI(最终)=80+15=95。此时数字变大,优先级下降了

核心口诀:

Nice 值为负数,进程变霸道,PRI 减小,优先级变高;

Nice 值为正数,进程变谦让,PRI 增大,优先级变低。

1.4 Nice 值的取值范围与限制原因

1.4.1 Nice 值的取值范围

为了防止某个进程无休止地调整 Nice 值从而彻底垄断或者搞崩溃系统,Linux 内核对 Nice 值的取值作了极其严格的界定:

Nice 值的取值范围 = [ − 20 , 19 ] \text{Nice 值的取值范围} = [-20, 19] Nice 值的取值范围=[−20,19]

总共只有 40 个级别

这意味着,无论你如何疯狂地尝试调小 Nice 值,系统允许的最低 Nice 值就是 -20。此时对应普通进程的最高优先级为 80 + ( − 20 ) = 60 80 + (-20) = 60 80+(−20)=60。同理,最低优先级为 80 + 19 = 99 80 + 19 = 99 80+19=99。

1.4.2 为什么要把 Nice 值的范围限制得这么小?

Linux 这样设计的根本目的,是为了防止"进程饥饿"(Process Starvation)

操作系统必须要做到公平调度 。如果允许用户无限度地拉高或降低进程优先级 ,那么某些高优先级的恶意进程将会死死霸占住 CPU 资源,导致其他普通的后台进程、系统维持进程永远分配不到 CPU 时间片 (这个概念在后面讲)。

长时间得不到 CPU 响应的进程就会在队列里"饿死",因此,Nice 值必须被锁死在固定的区间内。

1.5 优先级修改方法

1.5.1优先级调整的特点

优先级可以调整,不论是启动进程时还是进程运行中。

1.5.2 命令行与系统调用修改方法

1.5.2.1命令行工具
  • nice 命令:在启动进程时指定其初始 Nice 值。
  • renice 命令:在进程运行时动态调整其 Nice 值。

nice 示例:以较低优先级(Nice 值为 10)启动一个耗时的编译任务

bash 复制代码
nice -n 10 g++ main.cpp -o main

(注:如果不指定 -n 参数,nice 默认会把进程的 Nice 值设置为 10)

renice 示例:将一个正在运行的、PID 为 1234 的进程的 Nice 值调整为 5

bash 复制代码
renice -n 5 -p 1234

提高优先级(需要 root 权限):将 PID 为 1234 的进程 Nice 值降到 -5(优先级更高)

bash 复制代码
sudo renice -n -5 -p 1234
1.5.2.2系统调用

需要包含以下头文件及函数原型:

cpp 复制代码
#include <sys/time.h>
#include <sys/resource.h>

int getpriority(int which, int who);
int setpriority(int which, int who, int prio);
1.5.2.3通过top命令交互式修改
  1. 进入控制台 :在终端输入 top 运行性能监视器。
  2. 触发修改机制 :在 top 界面中按下键盘上的 r 键进入 renice 调整模式。
  3. 选择进程 PID
    • 此时界面会弹出提示:PID to renice [default pid = 24300]
    • 缺省参数 即为当前 top 列表中默认选中的 PID(如提示中的 24300)。
    • 如果想修改特定进程,手动输入目标进程 PID(例如输入 25110)并回车。
  4. 修改 Nice 值 :随后系统会提示 Renice PID 25110 to value ,在此处输入你期望修改的全新 Nice 值(范围通常为 -2019)并回车确认。




1.5.3权限与安全限制

注意 :出于安全考虑,操作系统不让你修改优先级过于频繁,可能会直接限制非 root 用户的降低 Nice 值(即提高优先级)操作。

解决方案 :切换成 root 用户或使用 sudo 权限进行操作。


好的本期内容就到这里,如果对你有帮助,还不要忘记点赞三联支持。我是此方,我们下期再见。bye!

相关推荐
路溪非溪6 小时前
Linux下物理总线驱动模型之SDIO驱动框架
linux·驱动开发
深圳市九鼎创展科技6 小时前
九鼎创展 X7110 开发板(JH7110):国产 RISC-V 多媒体平台全解析
大数据·linux·人工智能·嵌入式硬件·ubuntu·risc-v
流浪0016 小时前
Linux篇(八) Make 与 Makefile 超详细入门教程|从零基础到手写自动化编译
linux·运维·自动化
爱莉希雅&&&6 小时前
Redis哨兵模式和主从复制和集群模式搭建与扩容缩容
linux·redis·缓存·集群·哨兵·数据库同步
j_xxx404_6 小时前
Linux线程:从内存分页机制(Page Table/TLB/Page Fault)彻底读懂 Linux 线程本质
linux·运维·服务器·开发语言·c++·人工智能·ai
不做无法实现的梦~6 小时前
怎么实现codex控制嘉立创EDA绘制原理图
linux
青梅橘子皮7 小时前
Linux---冯诺伊曼体系结构,操作系统概况
java·linux·运维
I_am_Damon7 小时前
安全警告:该网站的安全证书存在问题
运维·服务器·安全
鹏大师运维7 小时前
不用装远程桌面!统信UOS通过SSH直接调用麒麟图形界面程序
linux·运维·网络·ssh·麒麟·x11·统信v25