4. 进程调度器

多进程运行原理

Linux内核具有进程调度器的功能,它使得多个进程能够同时运行。

  • 一个CPU同时只允许一个进程
  • 在同时允许多个进程时,每个进程都会获得适当的时长,轮流在CPU上执行处理

Linux会将多核CPU上的每个核心都识别为一个CPU。在本书中,我们将系统识别出来的CPU,称为逻辑CPU。另外,在开启了超线程功能时,每个线程都会被识别为一个逻辑CPU.

利用负载均衡功能,进程能够根据系统的负载跨逻辑CPU运行。

taskset -c 0 命令使得程序在指定的逻辑CPU上运行

上下文切换

上下文切换是指切换正在逻辑CPU上运行的进程。在进程0消耗完一定的时间片后进行上下文切换。

当一个时间片被消耗完后,不管进程正在执行什么代码,都一定会发生上下文切换

进程状态

使用ps ax命令可以按照一行一个进程的格式列举出系统中当前正在运行的所有进程。

该命令直接结果的总行数就是系统中正在运行的进程数量。
ps ax | wc -l

进程状态

状态名 含义
运行态 正在逻辑CPU上运行
就绪态 进程具备运行条件,等待分配CPU时间
睡眠态 进程不准备运行,除非发生某事件。在此期间不消耗CPU时间
僵死态 进程运行结束,正在等待父进程将其回收

处于睡眠态的进程所等待的事件有以下几种:

  • 等待指定的事件
  • 等待用户通过键盘或鼠标等设备进行输入
  • 等待HDD或SDD等外部存储器的读写结束
  • 等待网络的数据收发结束

通过ps ax命令结果的STAT列可以直到进程状态。

STAT字段的首字母 状态
R 运行态或就绪态
S或D 睡眠态。s指可通过接收信号回到运行态;D指S以外的情况(主要出现于等待外部存储器的访问时)
Z 僵死态

处于D状态的进程通常会在几毫秒之内迁移到别的状态。当长时间处于D状态的进程时,需要考虑是否发生了以下状况:

  • 存储器的I/O处理尚未结束
  • 内核中发生了某种问题

状态转换

进程在被创建后的整个生命周期中,会不断地在运行态、就绪态和睡眠态之间辗转,并非简单地使用完分配的CPU时间后就立刻结束。

空间状态

当CPU中没有进程在运行时,逻辑CPU会运行一个被称为空闲进程的不执行任何处理的特殊进程。
空闲进程最简单的实现方式就是创建一个新进程,或者在唤醒处于睡眠态的进程之前执行无意义的循环,但是这样会浪费电。
一般是使用特殊的CPU指令使逻辑CPU进入休眠状态,直到出现就绪态的进程。

计算机和智能手机之所以在不运行程序时能够待机更长时间,主要就得益于逻辑CPU能够进入空闲状态。

利用sar命令就可以确认单位时间内逻辑CPU处于空闲状态的时间占比,以及有多少空余的计算资源。

各种各样的状态转换

在现实中的系统中,各个进程会根据不同的处理转换到各种不同的状态,在逻辑CPU上运行的进程也会随之发生变化。

吞吐量与延迟

吞吐量: 单位时间内的总工作量,越大越好。
吞吐量 = 处理完成的进程数量 / 耗费的时间
CPU的计算资源消耗得越多,或者说空闲状态得时间占比越低,吞吐量就越大

通过sar -P ALL 1 1命令中%idle列得值越低,吞吐量越大

延迟: 各种处理从开始到完成所消耗的时间,越短越好
延迟 = 结束处理的时间 - 开始处理的时间

  • 在耗尽逻辑CPU的计算能力后,也就是说,当所有逻辑CPU都不处于空闲状态后,不管继续增加多少个进程,吞吐量都不会再发生变化
  • 随着进程数量的增加,延迟会越来越长
  • 每个进程的平均延迟是相等的

现实中的系统

  • 当逻辑CPU始终处于工作状态并且没有程序处于就绪态时,吞吐量与延迟就是最优值。

在现实中的系统中,逻辑CPU会在下列状态之间不断转换。

  • 空闲状态。由于逻辑CPU处于空闲状态,所以吞吐量会降低
  • 进程正在运行,且没有处于就绪态的进程,这是一种理想的状态。如果在这样的状态下加入一个处于就绪态的进程,则两个进程的延迟都会变长
  • 进程正在运行,且存在就绪态的进程。这时吞吐量很大,但是延迟会变长

为了使系统达到目标性能,也会对系统进行优化。

  • sar命令中的%idle字段
  • sar -q的runq-sz字段。该字段显示的是处于运行态或就绪态的进程总数(全部逻辑CPU的合计值)
    sar -q 1 1

存在多个逻辑CPU时的调度

为了能够利用各个逻辑CPU,调度器会运行一个被称为负载均衡全局调度的功能。负责公平地把进程分配给多个逻辑CPU。与只有单个逻辑CPU时的情况相同,在各个逻辑CPU内,调度器为在逻辑CPU上运行的各个进程分配均等的CPU时间。

  • 对于多核CPU的计算机来说,只有同时运行多个进程才能提高吞吐量。另外,"有n个核心就有n倍性能"这种说法,说到底也只存在于理想状态中
  • 与只有单个逻辑CPU时一样,当进程数量多于逻辑CPU数量时,吞吐量就不会再提高

运行时间和执行时间

  • 运行时间:进程从开始运行到运行结束为止所经过的时间

  • 执行时间:进程实际占用逻辑CPU的时长

  • 逻辑CPU数量=1, 进程数量 = 1
    time taskset -c 0 python3 hello.py

  • real:运行时间

  • user与sys的和为执行时间

  • user:表示进程在用户模式下消耗的CPU时间

  • sys:表示内核为了响应用户模式发出的请求而执行系统调用所耗费的时间

  • 逻辑CPU数量=2, 进程数量= 4

进程睡眠

time sleep 10

ps -eo pid,comm, etime, time命令

  • etime:表示进程从开始到执行命令为止的运行时间
  • time:表示进程从开始到执行命令为止的执行时间

变更优先级

系统一般会均等地分配CPU时间给所有可运行地进程。但是,为特定地进程指定优先级也是可以的。nice()就是为了实现这一点而提出的系统调用。

nice()能通过-19和20之间的数来设定进程的运行优先级(默认值为0),其中,-19的优先级最高,20的优先级最低。优先级高的进程可以比普通进程获得更多的CPU时间。

虽然谁都可以降低进程优先级,但是只有拥有root权限的用户才能进行提高优先级的操作

nice -n 优先级 程序

sar命令输出中%nice字段的值表示在从默认0更改为其他优先级后,进程运行时间所占的比例。
在不使用nice命令时,%user的值为100;
与此相对,在使用nice命令后,%nice的值变成了100

posted @ 2024-07-10 16:50  Python习者  阅读(9)  评论(0)    收藏  举报