欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第八部分(进程)

程序员文章站 2022-07-16 15:25:35
...

2020-04-09
Linux 内核通过使用进程来管理多任务。进程,就是 Linux 组织安排正在等待使用 CPU 的各种程序的方式。

进程是怎样工作的

当系统启动的时候,内核先把一些它自己的活动初始化为进程,然后运行一个叫做 init 的程序。init,依次地,再运行一系列的称为 init 脚本的 shell 脚本(位于/etc),它们可以启动所有的系统服务。其中许多系统服务以守护(daemon)程序的形式实现,守护程序仅在后台运行,没有任何用户接口 (User Interface)。这样,即使我们没有登录系统,至少系统也在忙于执行一些例行事务。

在进程方案中,一个程序可以发动另一个程序被表述为一个父进程可以产生一个子进程。

内核维护每个进程的信息,以此来保持事情有序。例如,系统分配给每个进程一个数字,这个数字叫做进程 (process) ID 或 PIDPID 号按升序分配,init 进程的 PID 总是 1。内核也对分配给每个进程的内存和就绪状态进行跟踪以便继续执行这个进程。像文件一样,进程也有所有者和用户 ID,有效用户 ID,等等。

查看进程

查看进程,最常使用地命令(有几个命令)是 ps(process status)。

[aaa@qq.com_0_7_centos ~]# ps
  PID TTY          TIME CMD
 7550 pts/0    00:00:00 bash
 8383 pts/0    00:00:00 ps
[aaa@qq.com_0_7_centos ~]# 

TTY 是 “Teletype”(直译电传打字机) 的简写,是指进程的控制终端。TTY 足足显示了 Unix 的年代久远。TIME 字段表示进程所消耗的 CPU 时间数量。

默认情况下,ps 不会显示很多进程信息,只是列出与当前终端会话相关的进程。
如果给 ps 命令加上选项,我们可以得到更多关于系统运行状态的信息:

[aaa@qq.com_0_7_centos ~]# ps x
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:39 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
    2 ?        S      0:00 [kthreadd]
...

加上 “x” 选项(注意没有开头的”-“ 字符),告诉 ps 命令,展示所有进程,不管它们由什么终端(如果有的话)控制。在 TTY 一栏中出现的 “?” ,表示没有控制终端。使用这个 “x” 选项,可以看到我们所拥有的每个进程的信息。
因为系统中正运行着许多进程,所以 ps 命令的输出结果很长。为了方便查看,将 ps 的输出管道到 less 中通常很有帮助。

输出结果中,新添加了一栏,标题为 STAT 。STAT 是 “state” 的简写,它揭示了进程当前状态:
第八部分(进程)
进程状态信息之后,可能还跟随其他的字符。这表示各种外来进程的特性。详细信息请看ps 手册页。

另一个流行的选项组合是 “aux”(不带开头的 “-” 字符)。这会给我们更多信息:

[aaa@qq.com_0_7_centos ~]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  43668  3404 ?        Ss   Mar18   0:39 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root         2  0.0  0.0      0     0 ?        S    Mar18   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    Mar18   0:20 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S<   Mar18   0:00 [kworker/0:0H]
...

这个选项组合,能够显示属于每个用户的进程信息。
通过这些选项,我们得到这些额外的列。
第八部分(进程)

用 top 命令动态查看进程

虽然 ps 命令能够展示许多计算机运行状态的信息,但是它只是提供 ps 命令执行时刻的机器状态快照。为了看到更多动态的信息,我们使用 top 命令:

[aaa@qq.com_0_7_centos ~]# top

top 程序以进程活动顺序显示连续更新的系统进程列表。(默认情况下,每三秒钟更新一次),“top” 这个名字来源于 top程序是用来查看系统中“顶端”进程的。top显示结果由两部分组成:最上面是系统概要,下面是进程列表,以 CPU 的使用率排序。

其中系统概要包含许多有用信息。下表是对系统概要的说明:

top - 14:59:20 up 6:30, 2 users, load average: 0.07, 0.02, 0.00
Tasks: 109 total, 1 running, 106 sleeping, 0 stopped, 2 zombie
Cpu(s): 0.7%us, 1.0%sy, 0.0%ni, 98.3%id, 0.0%wa, 0.0%hi, 0.0%si
Mem: 319496k total, 314860k used, 4636k free, 19392k buff
Swap: 875500k total, 149128k used, 726372k free, 114676k cach
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6244 me 39 19 31752 3124 2188 S 6.3 1.0 16:24.42 trackerd
....

第八部分(进程)

把一个进程放置到后台 (执行)

把终端想象是一个有前台(包含在表层可见的事物,像 shell 提示符)和后台(包含表层之下的隐藏的事物)(的设备)。为了启动一个程序并让它立即在后台运行,我们在程序命令之后,加上 “&” 字符:

[aaa@qq.com ~]$ xlogo &
[1] 28236
[aaa@qq.com ~]$

执行命令之后,这个 xlogo 窗口出现,并且 shell 提示符返回,同时打印一些有趣的数字。这条信息是 shell 特性的一部分,叫做任务控制 (job control)。通过这条信息,shell 告诉我们,已经启动了任务号 (job number) 为 1(“[1]”),PID 为 28236 的程序。

shell 的任务控制功能给出了一种列出从终端中启动了的任务的方法。执行 jobs 命令,我们可以看到这个输出列表:

[aaa@qq.com ~]$ jobs
[1]+ Running xlogo &

结果显示我们有一个任务,编号为“1”,它正在运行,并且这个任务的命令是 xlogo &

进程返回到前台

一个在后台运行的进程对一切来自键盘的输入都免疫,也不能用 Ctrl-c 来中断它。为了让一个进程返回前台 (foreground),这样使用 fg 命令:

[aaa@qq.com ~]$ jobs
[1]+ Running xlogo &
[aaa@qq.com ~]$ fg %1
xlogo

fg 命令之后,跟随着一个百分号和任务序号(叫做 jobspec, 如此处的%1)就可以了。如果我们只有一个后台任务,那么 jobspec(job specification) 是可有可无的。输入 Ctrl-c 来终止xlogo 程序。

停止一个进程

有时候,我们想要停止一个进程,而不是终止它。我们这么做通常是为了允许前台进程被移动到后台。输入 Ctrl-z,可以停止一个前台进程。
使用 fg 命令,可以恢复程序到前台运行,或者用 bg 命令把程序移到后
台。

[aaa@qq.com ~]$ xlogo
[1]+ Stopped xlogo
[aaa@qq.com ~]$
[aaa@qq.com ~]$ bg %1
[1]+ xlogo &
[aaa@qq.com ~]$

fg 命令一样,如果只有一个任务的话,jobspec 参数是可选的。

Signals

kill 命令被用来“杀死”程序。这样我们就可以终止需要杀死的程序。

[aaa@qq.com ~]$ xlogo &
[1] 28401
[aaa@qq.com ~]$ kill 28401
[1]+ Terminated xlogo

首先,我们在后台启动 xlogo 程序。shell 打印出这个后台进程的 jobspecPID。下一步,我们使用 kill 命令,并且指定我们想要终止的进程 PID。也可以用 jobspec(例如,“%1”)来代替 PID。

虽然这个命令看上去很直白,但是它的含义不止于此。这个 kill 命令不是真的“杀死”程序,而是给程序发送信号。信号是操作系统与程序之间进行通信时所采用的几种方式中的一种。在使用 Ctrl-cCtrl-z 的过程中我们已经看到信号的实际用法。当终端接受了其中一个按键组合后,它会给在前端运行的程序发送一个信号。在使用 Ctrl-c 的情况下,会发送一个叫做 INT(Interrupt, 中断)的信号;当使用 Ctrl-z 时,则发送一个叫做TSTP(Terminal Stop,终端停止)的信号。程序,相应地,监听信号的到来,当程序接到信号之后,则做出响应。一个程序能够监听和响应信号这件事允许一个程序做些事情,比如,当程序接到一个终止信号时,它可以保存所做的工作。

通过 kill 命令给进程发送信号

kill 命令被用来给程序发送信号。它最常见的语法形式看起来像这样:

kill [-signal] PID...

如果在命令行中没有指定信号,那么默认情况下,发送 TERM(Terminate,终止)信号。

kill 命令被经常用来发送以下命令:
第八部分(进程)

[aaa@qq.com ~]$ xlogo &
[1] 13546
[aaa@qq.com ~]$ kill -1 13546
[1]+ Hangup xlogo

在这个例子里,我们在后台启动 xlogo 程序,然后通过 kill 命令,发送给它一个 HUP 信号。这个 xlogo 程序终止运行,并且 shell 指示这个后台进程已经接受了一个挂起信号。在看到这条信息之前,你可能需要多按几次 enter 键。注意,信号既可以用号码,也可以用名字来指定,包括在前面加上字母“SIG”的名字。

[aaa@qq.com ~]$ xlogo 1] 13601
[aaa@qq.com ~]$ kill -INT 13601
[1]+ Interrupt xlogo
[aaa@qq.com ~]$ xlogo &
[1] 13608
[aaa@qq.com ~]$ kill -SIGINT 13608
[1]+ Interrupt xlogo

记住,你也可以用 jobspecs 来代替 PID

进程,和文件一样,拥有所有者,所以为了能够通过 kill 命令来给进程发送信号,你必须是进程的所有者(或者是超级用户)。

第八部分(进程)
第八部分(进程)
通过下面的命令可以得到一个完整的信号列表:

[aaa@qq.com_0_7_centos ~]# kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

通过 killall 命令给多个进程发送信号

也有可能通过 killall 命令,给匹配特定程序或用户名的多个进程发送信号。下面是 killall 命令的语法形式:

killall [-u user] [-signal] name...

记住,和 kill 命令一样,你必须拥有超级用户权限才能给不属于你的进程发送信号。

更多和进程相关的命令

第八部分(进程)