Program
是一个静态实体,只是存储在操作系统中的文件(集合)
Process
是操作系统上的活动(Active)实体,是 Program
由操作系统加载到内存并运行之后的实体。
Process
运行过程中需要操作系统为其分配各种资源,如 CPU、Memory、Files、IO 等来完成其运行。
如果一个 Program
被操作系统运行(启动)了多次,那么其产生的多个 Process
属于分割(单独)的实体。
Linux 系统中调度的进程/线程,通常被称为任务(Task)
Linux 中常见的进程状态如下表:
状态标识
状态名称
状态说明
示例
R
task_running
进程处于运行或就绪状态
S
task_interruptible
sleeping
可中断的睡眠状态
D
task_uninterruptible
不可中断的睡眠状态 1. 它是一种睡眠状态,意味着处于此状态的进程不会消耗 CPU 2. 睡眠的原因是等待某些资源(比如锁或者磁盘 IO),这也是非常多 D 状态的进程都处在处理 IO 操作的原因 3. 是它不能被中断,这个要区别于 硬件中断
的中断,是指不希望在其获取到资源或者超时前被终止。因此他不会被信号唤醒,也就不会响应 kill -9
这类信号。这也是它跟 S(可中断睡眠)
状态的区别
T
task_stopped
task_traced
Traced
暂停状态或跟踪状态
Z
task_dead
exit_zombie
zombie
退出状态,进程成为僵尸进程
X
task_dead
exit_dead
退出状态,进程即将被销毁
I
idle
空闲状态
+
表示关联了前台操作(Foreground Operation),比如前台运行的进程
进程调度 Linux 中任务(Task)调度算法默认使用 CFS(Completely Fair Scheduler,内核版本 >= 2.6.23).
CFS 调度算法没有使用固定的进程(此处的进程可能是进程或者线程,Linux 中统称为 Task)优先级(Priority),而是根据进程的 nice value
为进程分配一定比例的(Proportional) CPU 计算时间。 [1]
nice
的取值从 -20
- +19
,值越小,优先级越高,默认值为 0
。优先级高的进程会被分配到更高比例的 CPU 处理时间。
在 Linux 内核中,优先级分为两种:静态优先级和动态优先级。CFS 使用的是动态优先级,它是根据 nice
值计算出来的。
CFS Scheduler 不会直接设定 Priorities,而是为每个 Task 维护变量 vruntime(virtual runtime)
(可以检查系统 /proc/<PID>/sched
),这个值记录了每个 task 使用了多少 CPU 时间。
CFS 通过将进程的虚拟运行时间(vruntime
)与其他进程的虚拟运行时间进行比较来决定调度优先级。权重越大,vruntime
增长越慢,意味着进程的优先级越高,能够更频繁地被调度。
假入一个任务有默认的 Priority(nice=0
),那么他的 vruntime
和实际使用的 CPU 时间相同。例如一个 nice=0
的进程使用了 CPU 200ms,那么他的 vruntime=200ms
。低优先级(low priority,nice>0
) 的任务在 CPU 上运行了 200ms,那么他的 vruntime>200ms
,相反的,一个 高优先级(high priority,nice<0
) 的任务在 CPU 上运行了 200ms,那么他的 vruntime<200ms
。基于此,CFS Scheduler 在选择下一个要执行的任务时,会选择 vruntime
最小的任务来运行 。如果有高优先级的任务就绪(可执行),它会抢占(preemptive)正在执行的低优先级的任务。
假如 Linux 中有 2 个优先级一样的任务(nice=0
),一个进程为 I/O-bound,另一个为 CPU-bound。通常情况下,在一个 CPU 周期内,I/O-bound 的任务会使用很少的 CPU 时间就会因等待 IO 而中断在 CPU 上的执行并进入 CPU 的等待调度队列(schedule queue),而 CPU-bound 的任务会用尽分配给它的整个 CPU 周期。执行一段时间之后, I/O-bound 的任务的 vruntime
的值会显著的小于 CPU-bound 的任务的 vruntime
,导致 I/O-bound 的任务拥有比 CPU-bound 的任务更高的优先级,当 I/O-bound 的任务就绪(IO 返回数据)时,它会立即抢占 CPU 开始执行。
nice
只能针对单一的进程调整优先级,无法同时将优先级配置关联到相关进程,如 子进程或者同一个服务中的其他进程
修改 nice 的值 在 Linux 中,nice
值用于调整进程的优先级,数值范围从 -20
( 最高优先级 )到 19
( 最低优先级 )。较低的 nice
值表示进程有更高的优先级,会更频繁地获得 CPU 时间,而较高的 nice
值表示进程有较低的优先级。
你可以使用 nice
和 renice
命令来修改进程的 nice
值
普通用户(root
之外的用户)启动应用程序时默认只能配置初始 nice
值 0-19
普通用户(root
之外的用户)修改正在运行的应用程序的 nice
值,只能改大,不能改小。比如进程启动时,其 nice
为 10
,拥有权限的普通用户只能将其 nice
值改为大于 10
的值。
nice 命令 nice
命令用于在启动进程时指定 nice
值 。如果不指定,默认 nice
值为 0
。
renice 命令 renice
命令可以修改已经在运行的进程的 nice
值。需要提供进程 ID( PID )来指定要修改的进程。
renice <nice_value> -p <PID>
如果想要一次修改多个进程的 nice
值,可以传递多个 PID:
sudo renice 10 -p 1234 2345 3456
Linux 进程资源控制 cgroups cgroups
可以将一个任务(task
)标识(绑定)到一个特殊的 控制组(Control Group
) ,此任务启动的子进程可以继承父进程的 控制组(Control Group
)
控制组(Control Group
) 可以限制的资源类型如下:
Type
Description
blkio
Storage 限制到存储设备(如 Hard Disk、USB Drivers等)的请求
cpu
CPU 限制 CPU 调度
cpuacct
Process Accounting 上报 CPU 使用状态,可以用于统计客户端使用的处理量并进行收费
cpuset
CPU Assignment 在多处理器的系统上,将 Task 分配到特定的处理器以及关联的内存
devices
Device Access 限制 控制组(Control Group
) 中的 Task 对目标设备类型的使用
freezer
Suspend/Resume 暂停/恢复 控制组(Control Group
) 中的 Task
memory
Memory Usage 限制并报告 控制组(Control Group
) 中的 Task 使用的内存
net_cls
Network Bandwidth 制并报告 控制组(Control Group
) 中的 Task 使用的网络流量,主要通过对网络流量打上 cgroups
相关标签实现
net_prio
Network Traffic 控制 控制组(Control Group
) 中的网络流量的优先级
ns
Namespaces 将 cgroups
分配到不同的 Namespaces,如此同一个 cgroups
中的进程只能看到本 Namespace 中的进程
Linux 进程管理 进程命令名和进程可执行文件名 在系统中遇到以下进程:
# ps -elf | grep 18686 5 S root 18686 1239 0 80 0 - 46620 pipe_w 15:50 ? 00:00:00 /usr/sbin/CROND -n 0 R root 18694 18686 7 80 0 - 610547 - 15:50 ? 00:00:02 /usr/local/php73/bin/php /home/www/admin/artisan PullData 0 S root 18754 18686 0 80 0 - 22453 pipe_w 15:50 ? 00:00:00 /usr/sbin/sendmail -FCronDaemon -i -odi -oem -oi -t -f root
其中 PID 为 18686
的进程名为 /usr/sbin/CROND
,其启动了另外两个子进程。但是在系统中检查,并不存在路径 /usr/sbin/CROND
# ls -l /usr/sbin/CRONDls: cannot access /usr/sbin/CROND: No such file or directory
出现此种现象,主要是因为 在启动时,进程的命令名是根据路径传递给 execve()
函数的参数决定的,而不是直接与系统中的文件进行匹配 。
在 Linux 系统中,ps
命令显示的进程信息是从 /proc
文件系统中获取的,而 /proc
文件系统包含有关正在运行的进程的信息,包括每个进程的命令名。因此,即使实际上系统中不存在 /usr/sbin/CROND
文件,但如果进程的命令名是 /usr/sbin/CROND
,那么 ps
命令仍然会显示进程的命令名为 /usr/sbin/CROND
。
进程的命令名可以查看 /proc/<PID>/cmdline
文件 ,本示例中显示如下:
# cat /proc/18686/cmdline /usr/sbin/CROND-n
对应的系统上的可执行文件的名称可以查看 /proc/<PID>/stat
、/proc/<PID>/comm
、/proc/<PID>/status
等文件
# cat /proc/900/comm crond # cat /proc/900/status Name: crond Umask: 0022 State: S (sleeping) Tgid: 900 Ngid: 0 Pid: 900 PPid: 1239 TracerPid: 0 # cat /proc/900/stat900 (crond) S 1239 1239 1239 0 -1 4202816 1627 0 0 0 0 0 0 0 20 0 1 0 139129633 190955520 1478 18446744073709551615 94685936058368 94685936118156 140733000396032 140733000262488 140427856103840 0 0 4096 16387 18446744071797306256 0 0 17 3 0 0 0 0 0 94685938219080 94685938221648 94685948321792 140733000400770 140733000400789 140733000400789 140733000400872 0
在本示例中,实际执行的命令为 crond
进程状态检查 top 命令 使用 top
命令可以查看系统负载、CPU 和 内存使用情况。也可以查看单个进程的具体信息。
htop
是 top
命令的一个变种,它提供了更多的交互性、定制性以及其他一些功能,但是它同时使用了相比 top
更多的资源(4 倍多的 syscalls
)
top
命令常用选项
选项
说明
示例
-H
Threads Mode
,线程模式。默认情况 top
展示进程的简要信息,使用此选项显示进程中的线程状态。 对应交互式命令 H
top
常用交互命令
命令
说明
P
CPU Utilization 排序,默认排序方式
M
Memory Utilization 排序
I
Irix/Solaris-Mode 切换。 默认为 Itrix Mode,在这种模式下,如果某个进程使用了系统中的 2 个 CPU 的所有计算资源,则其 CPU 使用率展示为 200%,依此类推。 在 Solaris Mode 下,进程的 CPU 使用率是整体 CPU 使用的资源除于 CPU 数。如在 4 CPU 的系统中,Itrix 模式下,进程 CPU 使用率为 200%,在 Solaris 模式下,则为 50%
显示单个进程的(线程)详细信息 # top -H -p 1423 top - 09:44:42 up 54 days, 23:53, 2 users, load average: 8.82, 6.84, 7.21 Threads: 15 total, 0 running, 15 sleeping, 0 stopped, 0 zombie % Cpu(s): 40.9 us, 10.8 sy, 0.0 ni, 48.1 id , 0.0 wa, 0.0 hi, 0.2 si, 0.0 st KiB Mem : 15790488 total, 466056 free, 7761544 used, 7562888 buff/cache KiB Swap: 0 total, 0 free, 0 used. 3895716 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1423 root 20 0 1477368 778788 4260 S 39.5 4.9 11999:41 [watchdog:1:6] 2572 root 20 0 1477368 778788 4260 S 37.9 4.9 11363:48 [watchdog:1:6] 1436 root 20 0 1477368 778788 4260 S 34.2 4.9 11286:08 [watchdog:1:6] 1435 root 20 0 1477368 778788 4260 S 33.9 4.9 12059:53 [watchdog:1:6] 1434 root 20 0 1477368 778788 4260 S 33.2 4.9 10249:00 [watchdog:1:6] 1437 root 20 0 1477368 778788 4260 S 30.6 4.9 11717:47 [watchdog:1:6] 1431 root 20 0 1477368 778788 4260 S 28.9 4.9 11222:06 [watchdog:1:6] 21378 root 20 0 1477368 778788 4260 S 27.6 4.9 12143:35 [watchdog:1:6] 1433 root 20 0 1477368 778788 4260 S 17.6 4.9 8738:21 [watchdog:1:6] 1428 root 20 0 1477368 778788 4260 S 8.0 4.9 7650:56 [watchdog:1:6] 1429 root 20 0 1477368 778788 4260 S 0.0 4.9 0:00.04 [watchdog:1:6] 1430 root 20 0 1477368 778788 4260 S 0.0 4.9 0:00.05 [watchdog:1:6] 1432 root 20 0 1477368 778788 4260 S 0.0 4.9 0:00.03 [watchdog:1:6] 1438 root 20 0 1477368 778788 4260 S 0.0 4.9 12260:30 [watchdog:1:6] 1529 root 20 0 1477368 778788 4260 S 0.0 4.9 11068:39 [watchdog:1:6]
pidstat pidstat
命令用于检查 Linux 内核管理的进程的状态。帮助文档请查看 man pidstat
。要查看特定的进程的信息,使用 -p [PID|ALL]
选项,查看子进程相关信息,参考 -T [TASK | CHILD | ALL]
选项
命令常用选项
选项
说明
示例
-d
报告 I/O statistics
-C comm
查看 command name
的详细信息, comm
可以是正则表达式
pidstat -C chrome -T CHILD 1 10
-p { pid[,...] / SELF / ALL }
查看指定的 PID 或者所有(ALL) 进程的统计信息,不指定默认使用 -p ALL
-e program args
使用指定的 args
运行 program
并使用 pidstat
监控其统计数据
-l
在统计输出中,包含详细的命令及其参数
-r
统计进程的 faults
和 Memory 使用情况
-T { TASK / CHILD / ALL }
-t
查看子进程相关统计信息
-u
CPU 使用率
-w
统计进程上下文切换(Context Switch)信息
查看指定的 PID 以及关联的子进程的统计信息
# pidstat -t -p 22737 1 1 Linux 3.10.0-1160.49.1.el7.x86_64 (ecs-34a8) 11/26/2024 _x86_64_ (2 CPU) 04:04:52 PM UID TGID TID %usr %system %guest %CPU CPU Command 04:04:53 PM 0 22737 - 0.00 0.00 0.00 0.00 0 python3 04:04:53 PM 0 - 22737 0.00 0.00 0.00 0.00 0 |__python3 04:04:53 PM 0 - 22805 0.00 0.00 0.00 0.00 1 |__python3 04:04:53 PM 0 - 22806 0.00 0.00 0.00 0.00 0 |__python3 04:04:53 PM 0 - 22807 0.00 0.00 0.00 0.00 1 |__python3 04:04:53 PM 0 - 22808 0.00 0.00 0.00 0.00 0 |__python3 04:04:53 PM 0 - 22809 0.00 0.00 0.00 0.00 0 |__python3 04:04:53 PM 0 - 22810 0.00 0.00 0.00 0.00 1 |__python3 Average: UID TGID TID %usr %system %guest %CPU CPU Command Average: 0 22737 - 0.00 0.00 0.00 0.00 - python3 Average: 0 - 22737 0.00 0.00 0.00 0.00 - |__python3 Average: 0 - 22759 0.00 0.00 0.00 0.00 - |__python3 Average: 0 - 22806 0.00 0.00 0.00 0.00 - |__python3 Average: 0 - 22807 0.00 0.00 0.00 0.00 - |__python3 Average: 0 - 22808 0.00 0.00 0.00 0.00 - |__python3 Average: 0 - 22809 0.00 0.00 0.00 0.00 - |__python3 Average: 0 - 22810 0.00 0.00 0.00 0.00 - |__python3
查看进程使用的内存以及 faults
统计信息
# pidstat -r | more Linux 6.8.0-1017-aws (U-3TSDMAL9IVFAQ) 11/26/2024 _x86_64_ (4 CPU) 03:17:25 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command 03:17:25 PM 0 1 0.97 0.00 168668 13552 0.08 systemd 03:17:25 PM 0 147 1.85 0.00 228472 158232 0.98 systemd-journal 03:17:25 PM 0 189 0.00 0.00 289100 27392 0.17 multipathd 03:17:25 PM 0 199 0.00 0.00 12160 6376 0.04 systemd-udevd 03:17:25 PM 118 512 0.00 0.00 14624 6400 0.04 systemd-oomd 03:17:25 PM 100 551 0.00 0.00 16044 7296 0.05 systemd-network 03:17:25 PM 101 553 0.00 0.00 26512 10240 0.06 systemd-resolve 03:17:25 PM 0 643 0.00 0.00 2816 1920 0.01 acpid 03:17:25 PM 123 644 0.00 0.00 19088 3840 0.02 avahi-daemon 03:17:25 PM 102 645 0.00 0.00 31628 7436 0.05 dbus-daemon 03:17:25 PM 0 646 0.00 0.00 278416 14852 0.09 NetworkManager 03:17:25 PM 0 649 0.01 0.00 757540 17788 0.11 euc-analytics-a 03:17:25 PM 0 653 0.00 0.00 82768 3840 0.02 irqbalance 03:17:25 PM 0 656 0.00 0.00 48880 10368 0.06 networkd-dispat
查看进程使用的 CPU 统计信息
# pidstat -u -l | more Linux 6.8.0-1017-aws (U-3TSDMAL9IVFAQ) 11/26/2024 _x86_64_ (4 CPU) 04:08:08 PM UID PID %usr %system %guest %wait %CPU CPU Command 04:08:08 PM 0 1 0.04 0.02 0.00 0.02 0.06 1 /sbin/init 04:08:08 PM 0 2 0.00 0.00 0.00 0.00 0.00 0 kthreadd 04:08:08 PM 0 15 0.00 0.00 0.00 0.01 0.00 0 ksoftirqd/0 04:08:08 PM 0 49 0.00 0.00 0.00 0.00 0.00 2 khugepaged 04:08:08 PM 0 63 0.00 0.00 0.00 0.00 0.00 3 kworker/3:1H-kblockd 04:08:08 PM 0 64 0.00 0.00 0.00 0.00 0.00 3 kswapd0 04:08:08 PM 0 75 0.00 0.00 0.00 0.00 0.00 2 kworker/2:1H-kblockd 04:08:08 PM 0 100 0.00 0.00 0.00 0.00 0.00 0 jbd2/nvme0n1p1-8 04:08:08 PM 0 102 0.00 0.00 0.00 0.00 0.00 1 kworker/1:1H-kblockd 04:08:08 PM 0 129 0.00 0.00 0.00 0.00 0.00 0 kworker/0:1H-kblockd 04:08:08 PM 0 147 0.00 0.00 0.00 0.00 0.01 3 /lib/systemd/systemd-journald 04:08:08 PM 0 189 0.00 0.00 0.00 0.00 0.01 3 /sbin/multipathd -d -s 04:08:08 PM 0 199 0.00 0.00 0.00 0.00 0.00 3 /lib/systemd/systemd-udevd 04:08:08 PM 0 382 0.00 0.00 0.00 0.00 0.00 2 jbd2/nvme1n1p1-8 04:08:08 PM 118 512 0.05 0.05 0.00 0.00 0.10 3 /lib/systemd/systemd-oom d
在使用 pidstat
时如果未指定统计数据的采样间隔及采样次数,则 默认统计的是从系统启动以来的平均资源使用率,如果目标进程的运行时间相对于系统启动时间很短(例如仅几分钟),那么它的平均 CPU 使用率会趋近于 0 。比如以下示例:
未指定采样间隔及采样次数 ,统计结果显示进程的 CPU 使用率为 0
# pidstat | grep gzip 01:37:06 PM 0 784 0.00 0.00 0.00 0.00 4 gzip
以下命令指定采样间隔和采样次数 ,统计结果显示 CPU 使用率较高
# pidstat 1 1 | grep gzip 01:37:14 PM 0 1974 15.69 1.96 0.00 87.65 7 gzip Average: 0 1974 15.69 1.96 0.00 87.65 - gzip
参考链接|Bibliography Operating System Concepts v10 Online Linux进程状态说明
脚注