[toc]

什么是进程

  • 程序
    • 程序是数据和指令的集合,是一个静态的概念,比如/bin/ls、/bin/cp等二进制文件,同时程序可以长期存在系统中。
  • 进程
    • 进程是一个程序的运行过程,是一个动态概念,进程是存在生命周期概念的,也就是说进程会随着程序的终止而销毁,不会永远在系统中存在。
  • 进程的生命周期
    • 用户发起请求
    • 父进程会fork出子进程,子进程会继承父进程的大部分属性,如:文件描述等,处理任务
    • 子进程在处理任务的过程中,父进程是一个wait状态,等待子进程结束汇报
  • 僵尸进程
    • 子进程比父进程先结束,父进程没有回收子进程的资源,此时的子进程就称为”僵尸进程”
  • 孤儿进程
    • 父进程比子进程先结束,子进程还在执行任务,没有父进程管理,此时的子进程就称为“孤儿进程”

静态进程状态

ps(静态查看当前进程状态)

1
2
3
4
5
6
7
8
9
10
# ps(静态查看当前进程状态)

# 语法结构
ps 选项

# 选项
ps a # 显示所有与终端相关的进程,由终端发起的
ps u # 显示用户导向的用户列表
ps x # 显示所有与终端无关的进程
ps aux # 显示所有进程及用户列表

列标识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 列标识
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

# 各标识含义
USER # 启动程序的用户
PID # 进程ID
%CPU # 占用CPU的百分比
%MEM # 占用内存的百分比
VSZ # 占用虚拟内存的空间
RSS # 占用真实内存的空间
TTY # 运行的终端
?: ## 内核运行的终端
tty1: ## 机器运行的终端
pts/0: ## 远程连接的终端
STAT # 进程的状态
D: ## 无法中断的休眠状态(通IO的进程)
R: ## 正在运行的状态
S: ## 处于休眠的状态
T: ## 暂停或被追踪的状态
W: ## 进入内存交换(从内核2.6开始无效)
X: ## 死掉的进程(少见)
Z: ## 僵尸进程
<: ## 优先级高的进程
N: ## 优先级较低的进程
L: ## 有些页被锁进内存
s: ## 父进程(在它之下有子进程开启着)
l: ## 以线程的方式运行
|: ## 多进程的
+: ## 该进程运行在前台
START # 进程被触发开启的时间
TIME # 该进程实际使用CPU的运行时间
COMMAND # 命令的名称和参数
[]: ## 内核态的进程
没[]: ## 用户态的进程

ps命令用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ps(系统进程命令)

# 选项
-e # 列出所有进程
-f # 显示UID,PPIP,C与STIME栏位
-l # 以长格式显示
-a # 显示终端上的所有进程

# 常用语法
ps aux --sort 列标识|less # 对指定列标识下的进程进行排序

ps aux|sort -k区域 -n|grep 软件 # 对指定列所在区域下的进程进行倒叙排列,并过滤出指定软件的进程

ps auxf|grep [n]ginx # 过滤出指定软件的子进程
## 'grep [n]ginx'的正则表达式为'grep nginx',但'ps auxf'显示出的grep进程为'grep [n]ginx'

ps ax -o 列标识,列标识 # 自定义要显示的标识列

pidof 软件名 # 查看指定软件的pid

pgrep -l -a 软件名 # 过滤出指定软件并显示该进程的启动命令和完整描述信息
## -l:显示该进程的启动命令 -a:显示该进程的完整描述信息

pstree # 以树状图查看进程

动态进程状态

top(动态查看进程状态)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# top(动态查看进程状态)

# 常见指令
h # 查看帮出
z # 高亮显示
1 # 显示所有CPU的负载
s # 设置刷新时间
b # 高亮现实处于R(运行)状态的进程
M # 按内存使用百分比排序输出
P # 按CPU使用百分比排序输出
R # 对排序进行反转
f # 自定义显示字段
k # kill掉指定PID进程
W # 保存top环境设置 ~/.toprc
q # 退出

top列标识解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 列标识解析
## 第一行
top - 17:10:10 up 8:11, 1 user, load average: 0.00, 0.01, 0.05
top - 17:10:10 # 当前系统时间
up 8:11 # 开启时间
1 user # 几个用户同时在线
load average: 0.00, 0.01, 0.05 # 平均负载:1分钟,5分钟,15分钟

## 第二行
Tasks: 96 total, 1 running, 95 sleeping, 0 stopped, 0 zombie
Tasks: 96 total # 总进程数量
1 running # 正常运行进程数量
95 sleeping # 休眠状态进程数量
0 stopped # 停止状态进程数量
0 zombie # 僵尸状态进程数量

## 第三行
%Cpu(s): 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
0.0 us # 用户态:用户占用cpu的百分比
0.3 sy # 内核态:系统程序占用cpu的百分比(通常内核与硬件进行交互)
0.0 ni # 优先级:优先被调度的程序占用cpu的百分比
99.7 id # 空闲:cpu空闲的百分比
0.0 wa # 等待:cpu等待IO的完成时间
0.0 hi # 硬中断:占用cpu的百分比
0.0 si # 软中断:占cpu的百分比
0.0 st # 虚拟机占用物理机的百分比

## 第四行
KiB Mem : 995892 total, 597616 free, 99008 used, 299268 buff/cache
995892 total # 总内存大小
597616 free # 可用内存大小
99008 used # 已使用内存大小
299268 buff/cache # ***

## 第五行
KiB Swap: 1048572 total, 1048572 free, 0 used. 723692 avail Mem
1048572 total # 总虚拟内存大小
1048572 free # 可用虚拟内存大小
0 used # 已使用虚拟内存大小
723692 avail Mem # 实际可用虚拟内存大小

## 第六行
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
PID # 进程ID
USER # 运行进程的用户
PR # 优先级,正常为20
NI # nice值,正常为0,负值表示高优先级,正值标识低优先级
VIRT # 虚拟内存占用
RES # 真实内存占用
SHR # 共享内存占用
S # 模式状态
%CPU # cpu占用百分比
%MEM # 内存占用百分比
TIME+ # 运行时间
COMMAND # 运行命令

# PS:
## 硬中断:与系统相连的外设(比如网卡、硬盘)自动产生的。主要是用来通知操作系统,系统外设状态的变化。比如当网卡收到数据包的时候,就会发出一个中断。我们通常所说的中断指的是硬中断(hardirq)。
## 软中断:为了满足实时系统的要求,中断处理应该是越快越好。linux为了实现这个特点,当中断发生的时候,硬中断处理那些短时间就可以完成的工作,而将那些处理事件比较长的工作,放到中断之后来完成,也就是软中断(softirq)来完成。

进程管理命令

kill(进程关闭命令)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# kill(进程关闭命令)
kill -l # 列出所有支持的kill信号

# 常用信号
1 HUP # 挂起信号,往往可以让进程重新配置
2 INT # 中断信号,起到结束进程的作用,和ctrl + c 的作用一样
3 QUIT # 让进程退出,结果是进程退出
9 KILL # 直接结束进程,不能被进程捕获
15 TERM # 进程终止,这是默认信号
18 CONT # 被暂停的进程将继续恢复运行
19 STOP # 暂停进程
20 TSTP # 用户停止请求,作用类似于ctrl + z 把进程放到后台并暂停

# 常用命令
pkill # 杀掉所有进程,不用指定pid,可以后跟软件名
killall # 强制杀掉所有进程,不用指定pid,可以后跟软件名

nice(进程优先级)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# nice(进程优先级)
nice值越高:表示优先级越低,例如19,该进程优先将CPU使用量让给其他进程使用。
nice值越低:表示优先级越高,例如-20,该进程优先调用更多CPU资源。

# 什么是优先级
优先级别高的进程,可以优先享用系统的资源:cpu、内存、虚拟内存等

# 查看进程优先级
top # 在进程的PR列显示进程的nice值
ps axo aommand,nice|grep [软]件名 # 在进程nice列查看进程的nice值

# 设定进程优先级
nice -n -nice值 启动进程 # 指定启动进程优先级
renice -n -nice值 pid # 修改已运行进程优先级

# PS
修改完pid值,退出终端重新连接后查看,命令:exit(登出)

企业案例:Linux假死

什么是假死

所谓假死,就是能ping通,但是ssh不上去;任何其他操作也都没反应,包括上面部署的nginx也打不开页面。

假死其实很难出现一次

作为一个多任务操作系统,要把系统忙死,忙到ssh都连不上去,也不是那么容易的。尤其是现在还有fd保护、进程数保护、最大内存保护之类的机制。
你可以fork很多进程,系统会变得很慢,但是ssh还是能连上去;你可以分配很多内存,但是内存多到一定程度oom killer就会把你的进程杀掉,于是ssh又能工作了。

假死如何实现

有一个确定可以把系统搞成假死的办法是:主进程分配固定内存,然后不停的fork,并且在子进程里面sleep(100)。
也就是说,当主进程不停fork的时候,很快会把系统的物理内存用完,当物理内存不足时候,系统会开始使用swap;那么当swap不足时会触发oom killer进程;
当oom killer杀掉了子进程,主进程会立刻fork新的子进程,并再次导致内存用完,再次触发oom killer进程,于是进入死循环。而且oom killer是系统底层优先级很高的内核线程,也在参与死循环。

系统假死为何能ping同无法连接

此时机器可以ping通,但是无法ssh上去。这是由于ping是在系统底层处理的,没有参与进程调度;sshd要参与进程调度,但是优先级没oom killer高,总得不到调度。

出现假死怎么办

为什么要费那么大的力气把机器搞死?我们知道假死是怎么产生的即可,这样可以针对假死的原因进行预防。 (其实假死的情况很少发生,只有当代码写的bug很多的情况下会出现。)
其实建议使用nice将sshd的进程优先级调高。这样当系统内存吃紧,还能勉强登陆sshd,进入调试。然后分析故障。