Skip to content

LV220-进程管理命令简介

进程管理

程序的一次执行就是一个进程 ( process ) ,进程相关信息都可以在 /proc/ 目录下找到。

1. 显示进程的动态:ps

1.1 使用格式

在 linux 中,使用 man ps 命令就可以看到详细的帮助手册,我们会发现,这个命令不仅选项多,而且为了适应不同的类 UNIX 系统,可用格式也有好几种,很难记忆,下边只列举几个常用的。

shell
ps [option]

参数说明

  • option :选项。

该命令选项很多,这里只列举常用的几个参数说明。

option 说明
-A 显示所有进程
a 显示一个终端的所有进程,除会话引线外
u 显示进程的归属用户及内存的使用情况
x 显示没有控制终端的进程
-e 显示所有进程
-l 长格式显示更加详细的信息
-H 显示树状结构
-T 开启线程查看
#### 1.2 使用实例
1.2.1 查询指定进程情况

我们可以使用管道来只显示特定名称的进程运行情况,一般格式如下:

shell
ps [option] | grep <process_name>

例如,

shell
ps -elf | grep a.out

此命令后边较为常用,可能会多次用到,它将显示名称为 a.out 的所有进程的信息。

1.2.2 查看指定用户的进程
shell
ps -u <user_name>
1.2.3 查看指定进程的线程
shell
ps -L <PID>
ps -eLf |grep a.out # 查看指定名称为 a.out 的进程及其创建的所有线程。
1.2.4 ps -aux
shell
ps -aux

我是使用的 ubuntu ,在它里边加 - 或者不加好像都一样,使用 au 或者 aux 选项后,窗口会列出各进程的很多项信息,输出格式如下:

shell
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

进程信息参数说明如下:

USER 进程拥有者
PID pid
%CPU 占用的 CPU 使用率
%MEM 占用的记忆体使用率
VSZ 占用的虚拟记忆体大小
RSS 占用的记忆体大小
TTY 终端的次要装置号码 (minor device number of tty)
STAT 该进程的状态
D 不可被唤醒的睡眠状态,通常用于 I/O 情况。
R 该进程正在运行。
S 该进程处于睡眠状态,可被唤醒。
T 停止状态,可能是在后台暂停或进程处于除错状态。
Z 僵尸进程。进程已经中止,但是部分程序还在内存当中。
W 没有足够的记忆体分页可分配
< 高优先级(该状态在 BSD 格式中出现)。
N 低优先级(该状态在 BSD 格式中出现)。
L 被锁入内存(该状态在 BSD 格式中出现)。
s 包含子进程(该状态在 BSD 格式中出现)。
l 多线程(该状态在 BSD 格式中出现, 小写 L)。
+ 位于后台(该状态在 BSD 格式中出现)。
START 进程开始时间
TIME 执行的时间
COMMAND 所执行的指令
1.2.5 ps -le

该命令可以查看系统中所有的进程,而且还能看到进程的父进程的 PID 和进程优先级,使用该命令后,显示格式如下:

shell
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD

进程信息参数说明:

F 进程标志,说明进程的权限,常见的标志有两个:
1:进程可以被复制,但是不能被执行
4:进程使用超级用户权限
S 进程状态。具体的状态和 "psaux" 命令中的 STAT 状态一致
UID 运行此进程的用户的 ID
PID 进程的 ID
PPID 父进程的 ID
C 该进程的 CPU 使用率,单位是百分比
PRI 进程的优先级,数值越小,该进程的优先级越高,越早被 CPU 执行
NI 进程的优先级,数值越小,该进程越早被执行
ADDR 该进程在内存的哪个位置
SZ 该进程占用多大内存
WCHAN 该进程是否运行。"-" 代表正在运行
TTY 该进程由哪个终端产生
TIME 该进程占用 CPU 的运算时间,注意不是系统时间
CMD 产生此进程的命令名
1.2.6 ps -axjf

以树的形式列出终端的所有进程,可以与管道连用,查看一个进程的各个子进程的情况。

1.2.7 ps -eT

显示所有进程,并显示其子进程。使用命令后,显示信息格式如下:

shell
PID    SPID TTY          TIME CMD

其中 SPID 就表示线程号。该命令也可以有如下用法:

shell
ps -eT -p <pid>     # 显示指定的 PID 进程的所有线程
ps -eT | grep a.out # 显示进程 a.out 的所有线程
ps -T               # 显示进程及其创建的线程的信息

2. 实时显示进程:top

2.1 使用格式

该命令用于监视进程,通常会全屏显示,而且会随着进程状态的变化不断更新。整个系统的信息也会显示,为查找问题提供了便利。它可以显示系统总共有多少 CPU 和内存资源以及负载平衡等信息。

shell
top [option]

参数说明

  • option :选项
option 说明
-d 改变显示的更新速度,或是在交谈式指令列( interactive command)按 s
-q 没有任何延迟的显示速度,如果使用者是有 superuser 的权限,则 top 将会以最高的优先序执行
-c 切换显示模式,共有两种模式,一是只显示执行档的名称,另一种是显示完整的路径与名称
-S 累积模式,会将己完成或消失的子进程 ( dead child process ) 的 CPU time 累积起来
-s 安全模式,将交谈式指令取消, 避免潜在的危机
-i 不显示任何闲置 (idle) 或无用 (zombie) 的进程
-n 更新的次数,完成后将会退出 top
-b 批次档模式,搭配 "n" 参数一起使用,可以用来将 top 的结果输出到档案内
-p < PID> 显示指定 PID 的进程

2.2 显示信息详解

2.2.1 显示信息总览
shell
top - 16:28:51 up  8:30,  1 user,  load average: 0.08, 0.02, 0.00
任务: 296 total,   1 running, 295 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.5 us,  0.3 sy,  0.0 ni, 99.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3894.5 total,   1245.9 free,   1554.8 used,   1093.8 buff/cache
MiB Swap:   1162.4 total,   1162.4 free,      0.0 used.   2037.2 avail Mem 

 进程号 USER      PR  NI    VIRT    RES    SHR    %CPU  %MEM     TIME+ COMMAND
     1 root      20   0  165788  12284   7804 S   0.0   0.3   0:03.59 systemd
2.2.2 系统状态
shell
top - 16:28:51 up  8:30,  1 user,  load average: 0.08, 0.02, 0.00
top - 16:28:51 系统当前时间
up 8:30 系统到目前为止已运行的时间
1 user 当前登录系统的用户数量
load average: 0.08, 0.02, 0.00 系统负载(任务队列的平均长度),3 个数值分别为 1 分钟、5 分钟、15 分钟前到现在的平均值
##### 2.2.3 进程状态信息
shell
任务: 296 total,   1 running, 295 sleeping,   0 stopped,   0 zombie
任务: 296 total 所有启动的进程数
1 running 正在运行的进程数
295 sleeping 挂起的进程数
0 stopped 停止的进程数
0 zombie 僵尸进程数
2.2.4 CPU 占用情况
shell
%Cpu(s):  0.5 us,  0.3 sy,  0.0 ni, 99.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
0.5 us 用户空间占用 CPU 百分比
0.3 sy 内核空间占用 CPU 百分比
0.0 ni 用户进程空间内改变过优先级的进程占用 CPU 百分比
99.2 id 空闲 CPU 百分比
0.0 wa 等待输入输入的 CPU 百分比
0.0 hi 硬中断占用 CPU 百分比
0.0 si 软中断 CPU 百分比
0.0 st 虚拟 CPU 等待实际 CPU 的时间的百分比
2.2.5 Mem 内存信息(物理内存)
shell
MiB Mem :   3894.5 total,   1245.9 free,   1554.8 used,   1093.8 buff/cache
3894.5 total 物理内存总量
1245.9 free 空闲物理内存
1554.8 used 已经使用的物理内存
1093.8 buff/cache 内核缓存内存量
2.2.6 Swap 交换内存(虚拟内存)
shell
MiB Swap:   1162.4 total,   1162.4 free,      0.0 used.   2037.2 avail Mem
1162.4 total 交换区总量
1162.4 free 空闲交换区总量
0.0 used 已使用交互区总量
2037.2 avail Mem 缓冲的交换区总量
2.2.7 进程信息
shell
 进程号 USER      PR  NI    VIRT    RES    SHR    %CPU  %MEM     TIME+ COMMAND
PID 进程 ID
USER 进程所有者
PR 优先级
NI nice 值,负值表示高优先级,正值表示低优先级
VIRT 进程使用的虚拟内存总量, 单位 kb, VIRT = SWAP+RES
RES 进程使用的、未被换出的物理内存大小,单位 kb, RES = CODE+DATA
SHR 共享内存大小,单位 kb
%CPU 上传更新到现在的 CPU 时间占用百分比
%MEM 进程使用的物理内存百分比
TIME+ 进程使用的 CPU 时间总计,单位 1/100 秒
COMMAND 命令名/命令行

2.3 使用实例

shell
top -p <PID>  # 实时查看某个进程。

3. 以树状图显示进程:pstree

3.1 使用格式

shell
pstree [option] [PID或user_name]

参数说明

  • option :选项。
option 说明
-a 显示启动每个进程对应的完整指令,包括启动进程的路径、参数等
-c 不使用精简法显示进程信息,即显示的进程中包含子进程和父进程
-n 根据进程 PID 号来排序输出,默认是以程序名排序输出的
-p 显示进程的 PID
-u 显示进程对应的用户名称
- PID 或 user_name :要查看的进程的 PID 或者进程名。

3.2 使用实例

我们可以使用管道来只显示特定名称的进程运行情况:

shell
pstree [option] | grep <process_name>

# 例如
pstree -p |grep a.out

4. 终止进程:kill

4.1 使用格式

shell
kill -[signal] <PID>

kill 命令向指定的进程发出一个信号 signal ,在默认的情况下, kill 命令向指定进程发出信号 15 ,正常情况下,将杀死那些不捕捉或不忽略这个信号的进程。

参数说明

  • signal :要发送的信号编号。
signal 编号 signal 说明
0 EXIT 程序退出时收到该信息
1 HUP 进程重启,挂掉电话线或终端连接的挂起信号,这个信号也会造成某些进程在没有终止的情况下重新初始化
2 INT 表示结束进程,但并不是强制性的,常用的 "Ctrl+C" 组合键发出就是一个 kill -2 的信号
3 QUIT 退出
9 KILL 杀死进程,即强制结束进程
11 SEGV 段错误
15 TERM 正常结束进程,是 kill 命令的默认信号
还有很多其他的,后边慢慢会接触到,特别是学习进程通信方式——信号的时候。
  • PID :发送的信号的目标进程的进程 ID。

4.2 使用实例

shell
kill -9 8903 # 杀掉 PID 为 8903 的整个进程

5. 查看进程堆栈:pstack

5.1 使用格式

shell
sudo pstack <pid> # 一般是需要加上 sudo 的

【说明】 pstack 的工作原理其实就是一个 shell 脚本,在脚本里面调用 gdb 来实现对应用进程各个线程堆栈的打印。

5.2 安装与问题解决

该命令可以查看指定 PID 进程的堆栈情况,不过一般来说 Linux 中似乎不自带这个命令,需要自己安装,当我们直接输入 pstack 的时候可能会收到如下提示:

shell
Command 'pstack' not found, but can be installed with:
sudo apt install pstack

按照提示,我们在终端输入以下命令进行安装:

shell
sudo apt install pstack

然后我们直接输入一个进程号,使用 pstack 命令,例如在终端执行:

shell
pstack 14071 # 当时运行死锁一节笔记的测试例程时得到的进程号

然后很不幸,我们会得到如下报错:

shell
Could not attach to target 14071: Operation not permitted.
detach: No such process

可能是没有权限,我们加上 sudo :

shell
pstack 14071

很不幸,不出意外的话,我们可能会收到如下提示:

shell
14071: ./a.out
pstack: Input/output error
failed to read target.

这是怎么回事呢?不清楚啊,网上找了很久,似乎是因为这个命令 pstack 是一个脚本工具,它通过 apt 安装出来的程序好像是乱码,然后就不能运行了,我没有深究,按照解决办法,至少可以用了,后边研究明白了再补充吧。

  • 新建一个 pstack 文件
shell
vim pstack
  • 添加以下内容并保存文件
shell
#!/bin/sh
if test $# -ne 1; then
    echo "Usage:  basename $0 .sh  <process-id>" 1>&2
    exit 1
fi

if test ! -r /proc/$1; then
    echo "Process $1 not found." 1>&2
    exit 1
fi

# GDB doesn't allow "thread apply all bt" when the process isn't
# threaded; need to peek at the process to determine if that or the
# simpler "bt" should be used.

backtrace="bt"
if test -d /proc/$1/task ; then
    # Newer kernel; has a task/ directory.
    if test  /bin/ls /proc/$1/task | /usr/bin/wc -l  -gt 1 2>/dev/null ; then
    backtrace="thread apply all bt"
    fi
elif test -f /proc/$1/maps ; then
    # Older kernel; go by it loading libpthread.
    if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
    backtrace="thread apply all bt"
    fi
fi

GDB=${GDB:-/usr/bin/gdb}

if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then
    readnever=--readnever
else
    readnever=
fi

# Run GDB, strip out unwanted noise.
$GDB --quiet $readnever -nx /proc/$1/exe $1 <<EOF 2>&1 |
set width 0
set height 0
set pagination no
$backtrace
EOF
/bin/sed -n \
    -e 's/^\((gdb) \)*//' \
    -e '/^#/p' \
    -e '/^Thread/p'
  • pstack 配置到系统
shell
sudo cp pstack /usr/bin

5.3 使用实例

shell
sudo pstack <pid>

之前做测试的时候一个打印出来的效果如下:

shell
Thread 3 (LWP 14824 "a.out"):
#0  0x00007f2f4eb6dff0 in __lll_lock_wait () from /lib/x86_64-linux-gnu/libpthread.so.0
#1  0x00007f2f4eb66733 in pthread_mutex_lock () from /lib/x86_64-linux-gnu/libpthread.so.0
#2  0x00007ffd15297cde in ?? ()
#3  0x00005592ec341040 in ?? ()
#4  0x0000000000000000 in ?? ()
Thread 2 (LWP 14823 "a.out"):
#0  0x00007f2f4eb6dff0 in __lll_lock_wait () from /lib/x86_64-linux-gnu/libpthread.so.0
#1  0x00007f2f4eb66733 in pthread_mutex_lock () from /lib/x86_64-linux-gnu/libpthread.so.0
#2  0x00007ffd15297cde in ?? ()
#3  0x00005592ec341080 in ?? ()
#4  0x0000000000000000 in ?? ()
Thread 1 (LWP 14822 "a.out"):
#0  0x00007f2f4ea475df in clock_nanosleep () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x0000000000008000 in ?? ()
#2  0x0000000000000000 in ?? ()

6. 进程线程调度和优先级:chrt

6.1 使用格式

shell
chrt [options] -p [priority] pid # 一般是需要加上 sudo 的

【说明】 这里我就不详细说明了,具体的使用可以查看 man 手册。

6.2 使用实例

shell
hk@ubuntu-22-04:~$ chrt -m
SCHED_OTHER 最小/最大优先级	: 0/0
SCHED_FIFO 最小/最大优先级	: 1/99
SCHED_RR 最小/最大优先级	: 1/99
SCHED_BATCH 最小/最大优先级	: 0/0
SCHED_IDLE 最小/最大优先级	: 0/0
SCHED_DEADLINE 最小/最大优先级	: 0/0