今天来谈一下 Linux 进程相关。 参考:
进程的关系
为了能够在出现异常, 或者查看进程信息指标时对一个程序做更准确的控制,我们需要了解进程的用途与之间的关系。
比如说,启动了终端就是启动了一个 zsh 进程,我们可以在 zsh 中再输入 zsh 则会再启动一个 zsh 的进程,此时第二个 zsh 进程就是由第一个 zsh 进程创建出来的。我们一般称呼第一个 zsh 进程是第二 zsh 进程的父进程,第二 bash 进程是第一个 bash 进程的子进程。
既然子进程是通过父进程而衍生出来的,那么子进程的退出与资源的回收定然与父进程有很大的相关性。当一个子进程要正常的终止运行时,或者该进程结束时它会向父进程传递一个 SIGCHLD
信号,父进程做最后的资源回收与收尾工作。
特殊进程
1. 僵尸进程:
若是父进程没有做最后的收尾工作,导致进程的进程控制块(PCB)仍驻留在内存中,而PCB 的存在代表这个进程没有消亡(因为 PCB 就是进程存在的唯一标志,里面有 PID 等消息),这样的进程称之为僵尸进程(Zombie)。
2. 孤儿进程:
如果父进程结束(非正常的结束),未能及时收回子进程,子进程仍在运行,这样的子进程称之为孤儿进程。在 Linux 系统中,孤儿进程一般会被 init 进程所“收养”,成为 init 的子进程,由 init 来做善后处理。
3. 内核初始化进程:
进程 0 是系统引导时创建的一个特殊进程,也称之为内核初始化,其最后一个动作就是创建出一个子进程运行 /sbin/init 可执行文件,该子进程就是 PID=1 的进程 1,而进程 0 就转为交换进程(也被称为空闲进程),进程 1 (init 进程)是第一个用户态的进程,再由它不断创建系统里其他的进程,所以它是所有用户态进程的父进程或者祖先进程。同时它是一个守护程序,直到计算机关机才会停止。
进程的查看与分类
1 | ps -afxo user,ppid,pid,pgid,command |
pid
是该进程的一个唯一编号,ppid
就是该进程的父进程的 pid,command
表示的是该进程通过执行什么样的命令或者脚本而运行。
使用此命令我们也能清楚的看见, init 是由进程 0 这个初始化进程来创建而出的子进程, 而其他的进程基本是由 init 创建的子进程。所以 init 是用户进程的第一个进程也是所有用户进程的父进程或者祖先进程。
进程一般从两个角度分类:
1. 进程的功能与服务的对象
- 用户进程:执行用户程序、应用程序或者说内核之外的程序而产生的进程,此类进程可以在用户的控制下运行或关闭。
- 系统进程:通过执行系统内核程序而产生的进程,比如可以执行内存资源分配和进程切换等相对底层的工作;而且该进程的运行不受用户的干预,即使是 root 用户也不能干预系统进程的运行。
2. 应用程序的服务类型
交互进程:在执行过程中,需要与用户进行交互操作
批处理进程:该进程是一个进程集合,负责按顺序启动其他的进程。
守护进程:一直运行的一种进程,它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。例如 httpd 进程,还有 crontab 的守护进程,可以周期性的执行用户设定的某些任务。
工作管理
进程直接的父子关系只能描述比较浅的关系,若是同父进程的进程,并不能很好的描述,所以引入了进程组的概念,每一个进程都会是一个进程组的成员,以 PGID(process group ID)字段来描述。每当一个进程被创建的时候,它便会成为其父进程所在 Session 中的一员,每一个进程组都会在一个 Session 中,并且这个 Session 是唯一存在的。
一般情况,进程组的 PGID 等同于进程组的第一个成员的 PID,并且这样的进程称为该进程组的领导者, 也就是领导进程。 领导进程可以先终结,此时进程组依然存在,并持有相同的 PGID,直到进程组中最后一个进程终结。
Session 主要是针对一个 tty 建立,Session 中的每个进程都称为一个工作(job)。每个会话可以连接一个终端(control terminal)。当控制终端有输入输出时,都传递给该会话的前台进程。Session 意义在于将多个 jobs 囊括在一个终端,并取其中的一个 job 作为前台,来直接接收该终端的输入输出以及终端信号,其他 jobs 在后台运行。
前台 (foreground) 就是在终端中运行,能与用户有交互的进程。
后台 (background) 就是在终端中运行,但是并不能与用户交互,也不会显示其执行的过程。
若想将程序放入后台运行,常用此命令:
1 | bg [%jobnumber] |
其他可以用 Ctrl + z
, 或加上 &
。 [x] xxx
分别是 job number, PID, 若最后一行显示 done
, 表示已经在后台执行完毕。查看后台程序用 jobs
。 +
表示最新放入的job, -
表示倒数第二放入的job,没符号表示倒数第三以及之前放入的。
若想将后台程序拉回前台,用此命令:
1 | fg [%jobnumber] |
进程的控制
删除job:
1 | pkill <NAME> |
或者用:
1 | kill -signal %jobnumber # 控制进程 |
比如说:
1 | kill -9 1608 # 强制终止1608号任务 |
signal 有64个信号值可以选择,可以这样查看:
1 | kill -l |
常用的信号值:
信号值 | 作用 |
---|---|
-1 | 重新读取参数运行,类似restart |
-2 | 如同 ctrl+c 退出 |
-9 | 强制终止该任务 |
-15 | 正常的方式终止该任务 |
注意:
若是 kill + signal 然后直接加 pid,将会对 pid 对应的进程进行操作
若是 kill + signal 然后加
%jobnumber
,这时所操作的对象是 job,这个数字就是就当前 bash 中后台的运行的 job 的 ID
查看进程状态
接下来介绍一些常用的,查看进程状态的工具。
top
前台程序,实时、动态的显示当前系统中进程信息。好好利用 top 能够很有效的帮助我们观察到系统的瓶颈或问题所在。
Load Average
对当前 CPU 工作量的度量(等待 CPU 的平均进程数),分别对应1、5、15分钟内 CPU 的平均负载。
假设系统是单 CPU、单内核
- load = 0: CPU 没有任何任务
- load < 1: CPU 的任务并不多,资源还很充足
- load = 1:CPU 已经在全力工作,系统资源用完;但还在能力范围之内,只是有点慢
- load > 1: CPU 已经在全力工作,系统资源用完,但还有大量的进程在请求,在等待。若 >5, 说明系统已经在超负荷运作了
- load 的临界值为1, 但最佳临界值为0.7。先看 15 分钟的值来看大体趋势,再看 5 分钟的值对比是否有下降趋势。
查看 CPU 情况
查看 CPU 个数:
1 | cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l |
每个 CPU 核心数:
1 | cat /proc/cpuinfo | grep "physical id" | grep "0" | wc -l |
CPU利用率 (Column 3)
CPU 利用率是一个时间段内 CPU 使用状况的统计,通过这个指标可以看出在某一个时间段内 CPU 被占用的情况,而 Load Average 是 CPU 的 Load,它所包含的信息不是 CPU 的使用率状况,而是在一段时间内 CPU 正在处理以及等待 CPU 处理的进程数情况统计信息,这两个指标并不一样。
- us: 用户空间进程占用CPU百分比
- sy: 内核空间运行占用CPU百分比
- ni: 用户进程空间内,改变过优先级的进程占用CPU百分比
- id: 空闲CPU百分比
- wa: 等待输入输出的CPU时间百分比
- hi: 硬中断(Hardware IRQ)占用CPU的百分比
- si: 软中断(Software IRQ)占用CPU的百分比
- st: (Steal time) 是 hypervisor 等虚拟服务中,虚拟 CPU 等待实际 CPU 的时间的百分比
内存 (Column 4)
系统的中可用的物理内存最大值并不是 free 这个单一的值,而是 free + buffers + swap 中的 cached 的和。
- total: 物理内存总量
- used : 使用的物理内存总量
- free : 空闲内存总量
- buffers: 用作内核缓存的内存量
SWAP (Column 5)
- total: 交换区总量
- used : 使用的交换区总量
- free : 空闲交换区总量
- cached: 缓冲的交换区总量,内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖
进程
名称 | 解释 |
---|---|
PID | 进程id |
USER | 该进程的所属用户 |
PR | 该进程执行的优先级 priority 值 |
NI | 该进程的 nice 值 |
VIRT | 该进程任务所使用的虚拟内存的总数 |
RES | 该进程所使用的物理内存数,也称之为驻留内存数 |
SHR | 该进程共享内存的大小 |
S | 该进程进程的状态: S=sleep R=running Z=zombie |
%CPU | CPU的利用率 |
%MEM | 内存的利用率 |
TIME+ | 活跃总时间 |
COMMAND | 运行的名字 |
- NICE 值叫做静态优先级,是用户空间的一个优先级值,其取值范围是**-20至19**。这个值越小,表示进程”优先级”越高。 -20 优先级最高, 0 是默认的值,而 19 优先级最低。
- PR 值是动态优先级,是进程在内核中实际的优先级值,进程优先级的取值范围是通过一个宏定义的,这个宏的名称是 MAX_PRIO,它的值为 140。Linux 实际上实现了 140 个优先级范围,取值范围是从 0-139,这个值越小,优先级越高。而这其中的 0 - 99 是实时进程的值,而 100 - 139 是给用户的。
- 其中 PR 中的 100 to 139 值部分有这么一个对应
PR = 20 + (-20 to +19)
,这里的 -20 to +19 便是nice值,所以说两个虽然都是优先级,但是他们的值和作用范围并不相同 - VIRT 任务所使用的虚拟内存的总数,其中包含所有的代码,数据,共享库和被换出 swap空间的页面等所占据空间的总数
常用交互命令
- q: 退出程序
- I: Irix mode的开关 切换显示单核平均负载和CPU平均负载
- P: 根据CPU使用百分比大小进行排序
- M: 根据驻留内存大小进行排序
- i: 忽略闲置和僵死的进程,这是一个开关式命令
- k: 终止一个进程,系统提示输入 PID 及发送的信号值。一般终止进程用 15 信号,不能正常结束则使用 9 信号。安全模式下该命令被屏蔽。
ps
查看信息
1 | ps aux |
解释
内容 | 解释 |
---|---|
F | Process Flags, F = 1 表示此子程序只是 fork 但没有执行 exec,F = 4 表示此程序使用 root 权限 |
USER | 进程的拥有用户 |
PID | 进程 ID |
PPID | 父进程的 PID |
SID | session 的 ID |
TPGID | 前台进程组的 ID, -1的是守护进程 |
%CPU | 进程占用的 CPU 百分比 |
%MEM | 占用内存的百分比 |
NI | 进程的 NICE 值 |
VSZ | 进程使用虚拟内存大小 |
RSS | 驻留内存中页的大小 |
TTY | 终端 ID |
S / STAT | 进程状态 |
WCHAN | 正在等待的进程资源 |
START | 启动进程的时间 |
TIME | 进程消耗CPU的时间 |
COMMAND | 命令的名称和参数 |
进程状态 (STAT)
处在 D状态 的进程不接受外来的任何 signal,所以无法使用 kill 命令杀掉。 一般处于这种状态可能是进程 I/O 的时候出问题了。
状态 | 解释 |
---|---|
R | Running |
S | Interruptible Sleep. 等待调用 |
D | Uninterruptible Sleep. 不可中断睡眠 |
T | Stoped. 暂停或者跟踪状态 |
X | Dead. 即将被撤销 |
Z | Zombie |
W | Paging. 内存交换 |
N | 优先级低的进程 |
< | 优先级高的进程 |
s | 进程的领导者 |
L | 锁定状态 |
l | 多线程状态 |
- | 前台进程
常用参数
-l
: 此次登陆 bash 相关的进程信息ps aux
: 所有进程ps axjf
:树状显示ps -afxo user,ppid,pid,pgid,command
: 自定义需要显示的参数pstree
:pstree -up -A
: 各程序树之间以 ASCII 字元來连接pstree -up -p
: 同时列出每个 process 的 PIDpstree -up -u
: 同时列出每个 process 的所属账户名称