Linux 学习笔记(四)进程控制

来源:互联网 发布:棋魂软件下载 编辑:程序博客网 时间:2024/05/16 08:32

进程的组成部分

PID: 进程的 ID 号

PID - Process ID
内核给每个进程分配一个独一无二的 ID 号,控制进程的大多数命令和系统调用需要用户指定 PID 来标识操作的目标。PID 按照创建进程的顺序来分配。

PPID: 父 PID 号

PPID - Parent Process ID
当一个进程被克隆时,原来的进程就叫做父进程,而克隆出的副本则叫做子进程。进程的 PPID 属性就是克隆它的父进程的 PID。至少最初是这样。如果原来的父进程终止,那么init(进程 1)就成为新的父进程。

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

UID   - User ID
EUID - Effective User ID
进程的 UID 就是进程创建者的用户标识号,或者更确切地说,就是复制了父进程的的 UID 值。
EUID 是“有效(effective)”的用户 ID,这是一个额外的 UID,对于大多数进程而言,UID 和 EUID 是一样的,例外的情况是 setuid 程序。
Linux 还有一种“Saved User ID”,它是进程刚开始执行时刻,进程 EUID 的副本。除非进程采取措施删除这个保存下来的 UID,否则它就留了下来,作为真实的或者有效的 UID 来用。
Linux 还定义了一种非标准的进程参数 FSUID,它控制着对文件系统权限的判断,但在内核之外并不常用。

GID 和 EGID: 真实的和有效的组 ID

GID   - Group ID
EGID - Effective Group ID
GID 就是进程的组 ID。EGID 与 GID 的关系跟 EUID 与 UID 的关系相同,因为它可以由一个 setgid 程序来“转换”。Linux 有一种 SGID(Saved GID),就像有 Saved UID 一样。

信号(Signal)

信号是进程级的中断请求。《Linux Administration Handbook》一书上讲到“系统定义了大约 30 种不同种类的信号”,而现代 Linux 系统则定义了 64 种不同种类的信号。执行bash 的内置命令

$ kill -l

可以获得一份信号名称和编号的清单。(Ubuntu 10.10, Fedora 17)

 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL10) SIGUSR111) SIGSEGV12) SIGUSR213) SIGPIPE14) SIGALRM15) SIGTERM16) SIGSTKFLT17) SIGCHLD18) SIGCONT19) SIGSTOP20) SIGTSTP21) SIGTTIN22) SIGTTOU23) SIGURG24) SIGXCPU25) SIGXFSZ26) SIGVTALRM27) SIGPROF28) SIGWINCH29) SIGIO30) SIGPWR31) SIGSYS34) SIGRTMIN35) SIGRTMIN+136) SIGRTMIN+237) SIGRTMIN+338) SIGRTMIN+439) SIGRTMIN+540) SIGRTMIN+641) SIGRTMIN+742) SIGRTMIN+843) SIGRTMIN+944) SIGRTMIN+1045) SIGRTMIN+1146) SIGRTMIN+1247) SIGRTMIN+1348) SIGRTMIN+1449) SIGRTMIN+1550) SIGRTMAX-1451) SIGRTMAX-1352) SIGRTMAX-1253) SIGRTMAX-1154) SIGRTMAX-1055) SIGRTMAX-956) SIGRTMAX-857) SIGRTMAX-758) SIGRTMAX-659) SIGRTMAX-560) SIGRTMAX-461) SIGRTMAX-362) SIGRTMAX-263) SIGRTMAX-164) SIGRTMAX

下表列出了所有系统管理员都应该清楚的信号。

#名称描述 1  SIGHUP 挂起 2  SIGINT 中断 3  SIGQUIT 退出 9  SIGKILL 杀死 7  SIGBUS 总线错误 11  SIGSEGV 段错误 15  SIGTERM 软件终止 19  SIGSTOP 停止 20  SIGTSTP 键盘停止 18  SIGCONT 停止以后继续 28  SIGWINCH 窗口改变 10  SIGUSR1 用户定义 12  SIGUSR2 用户定义

kill 和 killall: 发送信号

顾名思义,kill 命令最直接的用法是终止一个进程。kill 能够发送任何信号,但在默认情况下,它发送一个 SIGTERM 信号。kill 可以被普通用户用在他们自己的进程上,或者被超级用户用在任何进程上。语法是:

# kill [-signal] pid

这里的 signal 就是要发送信号的编号或符号名称(如上表所示),pid 就是目标进程的 ID。pid 为 -1 会把这个信号广播给除了init 以外的所有进程。

没有信号编号的 kill 命令不保证进程会被杀死,因为 SIGTERM 信号可能被捕获、封锁或忽略。下面的命令:

# kill -SIGKILL pid

将“保证”进程的消亡,因为信号 9,即 SIGKILL 不能够被捕获到。我们给“保证”加引号是因为进程的生命力有时候能够变得相当“旺盛”,以致于连 SIGKILL 也不能够影响到它们(通常是由于有些退化的 I/O 虚假锁定,例如等待已经停止旋转的磁盘)。重新启动系统通常是解决这些“不听话”的进程的惟一方法。

如果用户不知道要发信号的进程的 PID,一般应该用 ps 命令查出来,另一种方法是使用 killall 命令,该命令替用户查出进程的 PID。例如:

$ sudo killall -SIGUSR1 xinetd

注意,如果用户的输入匹配多个进程,那么就会把 killall 信号发给所有匹配的进程。

普通的 kill 命令实际上有类似的功能,但是在匹配命令名上似乎没有 killall 那么聪明。所以还是坚持使用killall 吧。

ps: 监视进程

ps 是系统管理员监视进程的主要工具。用户可以用命令 ps aux 了解正在系统上运行的所有进程的全貌。

$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMANDroot         1  0.0  0.0   2880  1712 ?        Ss   19:23   0:00 /sbin/initroot         2  0.0  0.0      0     0 ?        S    19:23   0:00 [kthreadd]root         3  0.0  0.0      0     0 ?        S    19:23   0:00 [ksoftirqd/0]root         4  0.0  0.0      0     0 ?        S    19:23   0:00 [migration/0]root         5  0.0  0.0      0     0 ?        S    19:23   0:00 [watchdog/0]root         6  0.0  0.0      0     0 ?        S    19:23   0:00 [migration/1]root         7  0.0  0.0      0     0 ?        S    19:23   0:00 [ksoftirqd/1]root         8  0.0  0.0      0     0 ?        S    19:23   0:00 [watchdog/1]root         9  0.0  0.0      0     0 ?        S    19:23   0:00 [migration/2]root        10  0.0  0.0      0     0 ?        S    19:23   0:00 [ksoftirqd/2]root        11  0.0  0.0      0     0 ?        S    19:23   0:00 [watchdog/2]root        12  0.0  0.0      0     0 ?        S    19:23   0:00 [migration/3]root        13  0.0  0.0      0     0 ?        S    19:23   0:00 [ksoftirqd/3]

中括号括起来的命令名不是真正命令,而是按进程方式来调度运行的内核线程,有时候这些进程的名字以一个斜线加一个数字结尾,比如 [ksoftirqd/3],这个数字表明该线程在哪个处理器上运行,在多处理器的系统上会出现这种有意思的情况。

ps aux 命令输出的解释

字段内容 USER 进程的属主的用户名 PID 进程 ID %CPU 该进程正在使用的 CPU 百分比 %MEM 该进程正在使用的实际内存百分比 VSZ 进程的虚拟大小 RSS 驻留集的大小(内存中页的数量) TTY 控制终端的 ID STAT 当前进程的状态:
D = 等待磁盘
R = 在运行或可运行
S = 在睡眠(<20s)
T = 被跟踪或者被停止
W = 页面调度(2.6.xx 内核以上)
X = 死亡(正常情况下是看不到这个状态的)
Z = 僵死进程
附加标志:
< = 高优先级
N = 低优先级
L = 有些页面被锁在内存里
s = 进程是会话的先导进程
l = 进程是多线程
+ = 进程处于前台进程组 START 启动进程的时间 TIME 进程已经消耗掉的 CPU 时间 COMMAND 命令的名称和参数

另一组有用的选项是 lax,它提供了技术性更强的信息。

$ ps lax
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND4     0     1     0  20   0   2880  1712 poll_s Ss   ?          0:00 /sbin/init1     0     2     0  20   0      0     0 kthrea S    ?          0:00 [kthreadd]1     0     3     2  20   0      0     0 run_ks S    ?          0:00 [ksoftirqd/0]1     0     4     2 -100  -      0     0 cpu_st S    ?          0:00 [migration/0]5     0     5     2 -100  -      0     0 watchd S    ?          0:00 [watchdog/0]1     0     6     2 -100  -      0     0 cpu_st S    ?          0:00 [migration/1]1     0     7     2  20   0      0     0 run_ks S    ?          0:00 [ksoftirqd/1]5     0     8     2 -100  -      0     0 watchd S    ?          0:00 [watchdog/1]1     0     9     2 -100  -      0     0 cpu_st S    ?          0:00 [migration/2]1     0    10     2  20   0      0     0 run_ks S    ?          0:00 [ksoftirqd/2]5     0    11     2 -100  -      0     0 watchd S    ?          0:00 [watchdog/2]1     0    12     2 -100  -      0     0 cpu_st S    ?          0:00 [migration/3]1     0    13     2  20   0      0     0 run_ks S    ?          0:00 [ksoftirqd/3]

ps lax 的输出包括父进程 ID(PPID)、谦让值(NI)字段以及进程正在等待的资源(WCHAN)。

top: 更好地监视进程

由于 ps 这样的命令只提供系统过去时间的一次性快照,因此,要获得系统上正在发生事情的“全景”往往是非常困难的。top 命令对活动进程以及其所使用的资源情况提供定期更新的汇总信息。

$ top

/proc 文件系统

Linux 版的 ps 和 top 命令都从 /proc目录获取进程的状态信息,内核把有关系统状态的各种有意义的信息都放在这个伪目录里。虽然这个目录叫做/proc(下面的文件系统类型也叫做“proc”),但是它里面的信息却并局限于进程信息——内核产生的所有状态信息和统计数据都在这里。用户也可以通过向/proc 下的适当文件写入数据的方法来修改某些参数。

进程特有的信息都分别被放到了按 PID 起名字的子目录里。例如,/proc/1一定是包含 init 信息的目录。下表列出了各个进程最有用的文件,用户应该用 cat 或者 more 命令去看这些文件:

文件内容 cmdline 进程完整命令行(以 null 分隔) cwd 链到进程当前目录的符号链接 environ 进程的环境变量(以 null 分隔) exe 链到正被执行的文件的符号链接 fd 子目录,其中包含链到每个打开文件的描述符的链接 maps 内存映射信息(共享段、库等) root 链到进程的根目录(由 chroot 设置)的符号链接 stat 进程的总体状态信息(ps 最擅长解析这些信息) statm 内存使用情况的信息

cmdlineenviron 文件里的各个部分用空字符(null)而不是换行符(newline)分隔。用户可以借助命令

$ cat environ | tr "\000" "\n" | more

过滤掉这些文件的内容,使之可读性更好。

strace: 追踪信号和系统调用

将 strace 附在一个活动的 pid 进程上

$ sudo strace -p pid