Linux 进程管理详解

Linux 进程管理详解

进程 是 Unix 和 Linux 系统中对正在运行中的应用程序的抽象,通过它可以管理和监视程序对内存、处理器时间和 I / O 资源的使用。

一、进程的组成

一个进程包含内核中的一部分地址空间和一系列数据结构。其中地址空间是内核标记的一部分内存以供进程使用,而数据结构则用来纪录每个进程的具体信息。

最主要的进程信息包括:

  • 进程的地址空间图
  • 进程当前的状态( sleeping、stopped、runnable 等)
  • 进程的执行优先级
  • 进程调用的资源信息
  • 进程打开的文件和网络端口信息
  • 进程的信号掩码(指明哪种信号被屏蔽)
  • 进程的属主
PID :进程 ID

每个进程都会从内核获取一个唯一的 ID 值。绝大多数用来操作进程的命令和系统调用,都需要用 PID 指定操作的进程对象。

PPID :父进程 ID

在 Unix 和 Linux 系统中,一个已经存在的进程必须“克隆”它自身来创建一个新的进程。当新的进程克隆后,最初的进程便作为父进程存在。

UID & EUID:真实用户 ID 和有效用户 ID

一个进程的 UID 是其创建者的身份标志(也是对其父进程 UID 的复制)。通常只有进程的创建者和超级用户才有操作该进程的权限。
EUID 是一个额外的 UID,用来决定在任意一个特定时间点,一个进程有权限访问的文件和资源。对绝大多数进程而言,UID 和 EUID 是相同的(特殊情况即 setuid)

Niceness

一个进程的计划优先级决定了它能获取到的 CPU 时间。内核有一个动态的算法来计算优先级,同时也会关注一个 Niceness 值,来决定程序运行的优先顺序。

二、信号

信号属于进程级别的中断请求。它们可以作为进程间通信的手段,或者由终端发送以杀死、中断、挂起某个进程。

常见信号列表:

# name Description Default Can catch? Can block? Dump core?
1 HUP Hangup Terminate Yes Yes No
2 INT Interrupt(Ctrl + C) Terminate Yes Yes No
3 Quit Quit(Ctrl + \) Terminate Yes Yes Yes
9 KILL Kill Terminate No No No
BUS Bus error Terminate Yes Yes Yes
11 SEGV Segmentation fault Terminate Yes Yes Yes
15 TERM Software terminatation Terminate Yes Yes No
STOP Stop(Ctrl + Z) Stop No No No
TSTP Keyboard stop Stop Yes Yes No
CONT Continue after stop Ignore Yes No No

三、Kill 命令

kill 命令常用来终止某个进程,它可以向进程传递任意信号(默认为 TERM)。
kill [-signal] pid
不带任何数字(信号)选项的 kill 命令并不能保证指定进程被杀死,因为 kill 命令默认发送 TERM 信号,而 TERM 是可以被捕获、屏蔽或忽略的。
可以使用 kill -9 pid 命令强制杀死进程(9 代表 KILL 信号,不可被捕获、屏蔽或忽略)。

kill 命令需要指定进程的 PID 号。
pgrep 命令可以通过程序名称(或其他属性如 UID)筛选进程号,pkill 命令可以直接发送指定信号给筛选结果。
sudo pkill -u ben
该命令将发送 TERM 信号给所有属于用户 ben 的进程。

killall 命令可以通过程序名称杀死指定进程的所有实例。如:
sudo killall apache2

$ pgrep postgres  # 筛选 postgres 进程的 PID 号 
25874
25876
25877
25878
25879
25880
25881
$ pgrep -a postgres  # 筛选 postgres 进程的 PID 号,并输出详细信息
25874 /usr/lib/postgresql/10/bin/postgres -D /var/lib/postgresql/10/main -c config_file=/etc/postgresql/10/main/postgresql.conf
25876 postgres: 10/main: checkpointer process
25877 postgres: 10/main: writer process
25878 postgres: 10/main: wal writer process
25879 postgres: 10/main: autovacuum launcher process
25880 postgres: 10/main: stats collector process
25881 postgres: 10/main: bgworker: logical replication launcher

$ sudo kill -9 `pgrep postgres`  # 杀死 postgres 进程
$ sudo pkill postgres  # 同上一条命令
$ sudo killall postgres  # 杀死 postgres 进程的所有实例
$ sudo pkill -9 -u postgres  # 杀死属于 postgres 用户的所有进程

根据进程 PID 号查找进程可以使用 ps -p -o comm= 命令

四、进程状态

状态 含义
Runnable 该进程正在(正准备)执行
Sleeping 该进程正等待某些资源
Zombie 该进程正努力尝试结束
Stopped 该进程已挂起(不允许执行)
  • Runnable 表示进程已经获取到了运行所需的所有资源,只是等待相应的 CPU 时间来处理数据。
  • Sleeping 表示进程处于等待特定事件发生的状态。交互式 Shell 和系统守护进程的大部分时间都是 Sleeping 状态,等待用户输入或网络连接。
  • Zombies 表示进程已经结束执行,但是还没有收集完所有的状态,在进程表中仍有纪录。
  • Stopped 表示进程已停止运行,通常是收到了某种停止信号。

五、PS 命令:监控资源

ps 命令是系统管理员监控进程的主要工具。该命令可以显示进程的 PID、UID、优先级和控制终端,以及进程占用的内存、消耗的 CPU 时间和当前的状态等信息。

常用的 PS 命令选项组合:

1. ps aux

a 选项表示显示所有进程,x 选项表示同时显示没有控制终端的进程(TTY 显示为 ?),u 选项表示使用基于用户的信息输出格式

$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1 225428  9548 ?        Ss   7月30   0:30 /lib/systemd/systemd --system --deserialize 19
root         2  0.0  0.0      0     0 ?        S    7月30   0:00 [kthreadd]
root         4  0.0  0.0      0     0 ?        I<   7月30   0:00 [kworker/0:0H]
root         6  0.0  0.0      0     0 ?        I<   7月30   0:00 [mm_percpu_wq]
root         7  0.0  0.0      0     0 ?        S    7月30   0:03 [ksoftirqd/0]
root         8  0.0  0.0      0     0 ?        I    7月30  14:49 [rcu_sched]
...
starky    6874  0.0  0.1  33016  8556 pts/2    Ss   8月07   0:00 bash
starky    7150  0.0  0.0  33016  6044 pts/2    S+   8月07   0:00 bash
starky    7151  3.1 16.1 4763784 1227932 pts/2 Sl+  8月07 272:54 java -Xmx1024M -Xms512M -jar minecraft_server.1.12.2.jar nogui
...
root     18447  0.0  0.0 107984  7116 ?        Ss   13:55   0:00 sshd: starky [priv]
starky   18535  0.0  0.0 108092  4268 ?        S    13:55   0:00 sshd: starky@pts/1
starky   18536  0.0  0.1  33096  8336 pts/1    Ss   13:55   0:00 -bash
root     18761  0.0  0.0      0     0 ?        I    13:55   0:00 [kworker/u8:0]
root     18799  0.0  0.0      0     0 ?        I    14:01   0:00 [kworker/u8:1]
root     18805  0.0  0.0      0     0 ?        I    14:05   0:00 [kworker/0:2]
starky   18874  0.0  0.0  46780  3568 pts/1    R+   14:10   0:00 ps -aux
redis    19235  0.2  0.0  58548  3736 ?        Ssl  8月04  30:03 /usr/bin/redis-server 127.0.0.1:6379
root     20799  0.0  0.0 107548  7504 ?        Ss   8月05   0:00 /usr/sbin/cupsd -l
root     28342  0.0  0.4 535068 36940 ?        Ss   8月10   0:16 /usr/sbin/apache2 -k start

其中带中括号的命令(如 [kthreadd])并不是真正的命令而是内核线程。

ps aux 命令输出的各列信息含义如下:

项目 解释
USER 进程属主的用户名
PID 进程 ID
%CPU 进程占用的 CPU 百分比
%MEM 进程使用的内存百分比
VSZ 进程的虚拟大小
RSS 驻留内存大小(内存中的页数)
TTY 控制终端 ID
STAT 进程当前的状态: R = Runnable D = In uninterruptible sleep S = Sleeping(<20s) T = Traced or stopped Z = Zombie 额外标记: W = Process is swapped out < = 进程有相对于平时更高的优先级 N = 进程有相对于平时更低的优先级 L = Some pages are locked in core s = Process is a session leader
TIME 进程已经消耗的 CPU 时间
COMMAND 进程的命令和命令选项
2. ps lax

l 选项表示以详细的格式输出进程信息。

$ ps lax
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
4     0     1     0  20   0 225428  9548 -      Ss   ?          0:30 /lib/systemd/systemd --system --deserialize 19
1     0     2     0  20   0      0     0 -      S    ?          0:00 [kthreadd]
1     0     4     2   0 -20      0     0 -      I<   ?          0:00 [kworker/0:0H]
1     0     6     2   0 -20      0     0 -      I<   ?          0:00 [mm_percpu_wq]
1     0     7     2  20   0      0     0 -      S    ?          0:03 [ksoftirqd/0]
1     0     8     2  20   0      0     0 -      I    ?         14:58 [rcu_sched]
...
0  1000  6874  6871  20   0  33016  8556 wait   Ss   pts/2      0:00 bash
1  1000  7150  6874  20   0  33016  6044 wait   S+   pts/2      0:00 bash
0  1000  7151  7150  20   0 4763784 1227932 futex_ Sl+ pts/2  275:03 java -Xmx1024M -Xms512M -jar minecraft_server.1.12.2.jar nogui
...
4     0 18447   619  20   0 107984  7116 -      Ss   ?          0:00 sshd: starky [priv]
5  1000 18535 18447  20   0 108092  4268 -      S    ?          0:00 sshd: starky@pts/1
0  1000 18536 18535  20   0  33096  8336 wait   Ss   pts/1      0:00 -bash
1     0 19051     2  20   0      0     0 -      I    ?          0:00 [kworker/3:0]
1     0 19141     2  20   0      0     0 -      I    ?          0:00 [kworker/2:3]
1   115 19235     1  20   0  58548  3736 -      Ssl  ?         30:22 /usr/bin/redis-server 127.0.0.1:6379
1     0 19246     2  20   0      0     0 -      I    ?          0:00 [kworker/2:0]
1     0 19291     2  20   0      0     0 -      I    ?          0:00 [kworker/u8:0]
1     0 19312     2  20   0      0     0 -      I    ?          0:00 [kworker/0:2]
1     0 19405     2  20   0      0     0 -      I    ?          0:00 [kworker/u8:1]
0  1000 19417 18536  20   0  36024  1596 -      R+   pts/1      0:00 ps -lax
4     0 20799     1  20   0 107548  7504 -      Ss   ?          0:00 /usr/sbin/cupsd -l
5     0 28342     1  20   0 535068 36940 -      Ss   ?          0:16 /usr/sbin/apache2 -k start

ps lax 命令的输出包含了父进程 ID(PPID)、nice 值(NI)还有进程正在等待的资源类型(WCHAN)等。

3. ps axjf

ps axjf 命令能够以树状结构显示各进程间的层级关系
f 选项表示用 ASCII 字符显示树状结构,表达程序间的相互关系。

$ ps axjf
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
    2     4     0     0 ?           -1 I<       0   0:00  \_ [kworker/0:0H]
    2     6     0     0 ?           -1 I<       0   0:00  \_ [mm_percpu_wq]
    2     7     0     0 ?           -1 S        0   0:02  \_ [ksoftirqd/0]
    2     8     0     0 ?           -1 I        0   4:26  \_ [rcu_sched]
...
    1   672   672   672 ?           -1 Ss       0   0:00 /usr/sbin/sshd -D
  672 27078 27078 27078 ?           -1 Ss       0   0:00  \_ sshd: starky [priv]
27078 27166 27078 27078 ?           -1 S     1000   0:00      \_ sshd: starky@pts/1
27166 27167 27167 27167 pts/1    27438 Ss    1000   0:00          \_ -bash
27167 27438 27438 27167 pts/1    27438 R+    1000   0:00              \_ ps axjf
    1   681   681   681 ?           -1 Ssl    115   9:40 /usr/bin/redis-server 127.0.0.1:6379
    1   700   700   700 tty1       700 Ss+      0   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
    1   710   710   710 ?           -1 Ss       0   0:14 /usr/sbin/apache2 -k start
  710 25651   710   710 ?           -1 S       33   0:00  \_ /usr/sbin/apache2 -k start
  710 25652   710   710 ?           -1 S       33   0:00  \_ /usr/sbin/apache2 -k start
  710 25653   710   710 ?           -1 S       33   0:00  \_ /usr/sbin/apache2 -k start
  710 25654   710   710 ?           -1 S       33   0:00  \_ /usr/sbin/apache2 -k start
  710 25655   710   710 ?           -1 S       33   0:00  \_ /usr/sbin/apache2 -k start
  ...
4. ps o

ps o 命令加上选项可以指定信息的输出格式,同时加上 --sort 选项可指定排序依据
如:ps axo pid,ppid,%mem,%cpu,cmd --sort=-%mem
上面的命令表示输出进程的 PID、PPID、内存占用、CPU占用和命令选项。并以内存占用大小排序。(--sort=-%mem 中的 - 表示逆向排序,即由大到小排序)

$ ps axo pid,ppid,%mem,%cpu,cmd --sort=-%mem | head
  PID  PPID %MEM %CPU CMD
 1790  1789 14.1  3.8 java -Xmx1024M -Xms512M -jar minecraft_server.1.12.2.jar nogui
 1357     1  2.6  0.1 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid
 9343     1  2.0  0.0 /usr/bin/python3 /usr/bin/update-manager --no-update --no-focus-on-map
 1244     1  1.5  0.0 sogou-qimpanel %U
 1024     1  1.0  0.0 /usr/bin/fcitx
 1454     1  0.9  0.0 fcitx-qimpanel
 7401  1067  0.7  0.0 lxterminal
  248     1  0.6  0.0 /lib/systemd/systemd-journald
 1119     1  0.6  0.0 nm-applet

可以尝试不同的命令选项组合来获取相应的信息,具体可参考 man ps

六、使用 TOP 命令动态监控进程

top 命令可以实时显示系统当前活跃进程的总体信息及其占用的资源。

img

top

top-d

命令 描述
h 显示帮助信息
k 终止某个进程
i 忽略闲置和僵死进程(这是一个开关式命令)
q 退出 top 程序
r 重新设置某个进程的优先级
s 改变两次刷新之间的延迟时间(单位为s)
f 或 F 从当前显示中添加或者删除项目
l 切换显示平均负载和启动时间信息
m 切换显示内存信息
t 切换显示进程和CPU状态信息
c 切换显示命令名称和完整命令
M 根据驻留内存大小进行排序
P 根据CPU使用百分比大小进行排序
T 根据时间/累计时间进行排序
w 将当前设置写入 ~/.toprc 文件中

七、前台/后台进程

  • 前台进程(也称作交互式进程):由某个终端会话创建和控制的进程。即需要用户控制而不能作为系统服务自动启动。
  • 后台进程(也称作非交互式进程):不和终端绑定的进程,不等待用户输入。

可以在命令后带上 & 符号,在后台启用一个 Linux 进程执行该命令。并通过 jobs 命令查看当前的任务。
使用 fg 命令将后台执行的进程调到前台执行
使用 Ctrl + Z 组合键(发送 SIGSTOP 信号)挂起当前进程(前台),并使用 bg 命令令其在后台继续执行

$ python -m SimpleHTTPServer &  # 后台启动 python 进程
[1] 28036
$ Serving HTTP on 0.0.0.0 port 8000 ...

$ jobs                          # 使用 jobs 命令查看后台进行的任务
[1]+  运行中               python -m SimpleHTTPServer &
$ fg %1                         # 将后台执行的第一个任务调到前台执行(fg %1)
python -m SimpleHTTPServer
^Z                              # 使用 Ctrl + Z 组合键(发送 STOP 信号)停止当前进程
[1]+  已停止               python -m SimpleHTTPServer
$ bg                            # 使用 bg 命令将进程调至后台继续执行
[1]+ python -m SimpleHTTPServer &
$ fg %1
python -m SimpleHTTPServer
             # 将后台执行的第一个任务调到前台执行(fg %1)
python -m SimpleHTTPServer
^Z                              # 使用 Ctrl + Z 组合键(发送 STOP 信号)停止当前进程
[1]+  已停止               python -m SimpleHTTPServer
$ bg                            # 使用 bg 命令将进程调至后台继续执行
[1]+ python -m SimpleHTTPServer &
$ fg %1
python -m SimpleHTTPServer
发布了87 篇原创文章 · 获赞 232 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_43518645/article/details/105279522