文章目录
- 2、控制进程
- 3、信号
现代操作系统通常都支持多重任务处理(multitasking)。多重任务处理是指系统通过快速切换运行中的程序来实现多任务的同时执行。Linux内核通过使用进程来管理多重任务。进程是Linux用来安排不同程序等待CPU调度的一种组织方式。
1、进程如何工作
系统启动时,内核先把它的一些程序初始化为进程,然后运行一个称为init
的程序。init
程序将依次运行一系列称为脚本初始化(init script)的shell脚本(放在/etc目录下),这些脚本将会启动所有的系统服务。其中的很多服务都是通过守护程序(daemon program)来实现的。而后台程序只是待在后台做它们自己的事情,并且没有用户界面。因此,即使没有用户登录,系统也在忙于执行一些例行程序。
一个程序的运行可以出发其他程序的运行,在进程系统中这种情况被表述为:父进程创建子进程。
内核会保存每个进程的信息以便确保任务有序进行。比如,每个进程将被分配一个称为进程ID(PID,progress ID)的号码。进程ID是按递增的顺序来分配的,init进程的PID始终为1。内核也记录分配给每个进程的内存信息以及用来恢复运行的进程就绪信息。和文件系统类似,进程系统中也存在所有者、用户ID、有效用户ID等。
1.1、ps–查看进程信息
用来查看进程信息的命令中(有多个),使用最普遍的就是ps命令。ps命令有很多选项,其中最简单的使用格式如下所示:
这个例子的输出结果列出了两个进程:进程1088和进程1182,它们分别对应bash
命令和ps
命令。TTY是teletype(电传打字机)的缩写,代表了进程的控制终端(controlling terminal)。UNIX在这里也显示了进程的运行时间,TIME字段表示子进程消耗CPU时间总和。可以看出,这两个进程都没有使计算机变得忙碌。
我们可以发现,默认情况下,ps
命令输出的信息并不是很多,只是输出和当前终端会话相关的进程信息。为了获得更多的信息,我们需要添加一些选项。如果在ps
命令后添加一个选项,那么我们将得到反映系统运行情况的更大视图界面,如下所示:
添加x选项(注意这里没有前置的连字符)将告知ps
命令显示所有的进程,而不需要关注他们是由哪个终端(如果由其他的情况)所控制的。TTY列中出现的“?”表示没有控制终端,使用这个选项可以查看所有进程的列表信息。
由于系统中运行着大量的进程,所以ps
命令将会输出一个长列表。把ps
命令的输出作为less命令输入的方法通常很管用,它可以更方便的查看显示结果。有些选项组合也会产生很长的输出行,因此最大化终端仿真窗口也是一个好主意。
输出结果中添加了一个命名为SATA的新列。SATA是state的缩写,显示的是进程的当前状态:
状态 | 含义 |
R | 运行状态。进程正在运行或者准备运行 |
S | 睡眠状态。进程不在运行,而是在等待某事件发生,如键盘输入或者受到网络报文 |
D | 不可中断的睡眠状态。进程在等待I/O操作,如硬盘驱动 |
T | 暂停状态。进程被指示暂停(后续还可以继续运行) |
Z | 无效或者“僵尸”进程。子进程被终止,但是还没有被其父进程彻底释放掉 |
< | 高优先级进程。进程可以被赋予更多的重要性,分配更多的CPU时间。进程的这一特性称为优先级(niceness)。高优先级的进程被说成比较不友好,是因为它将消耗更多的CPU时间,这一留给其他进程的CPU时间就会变少 |
N | 低优先级进程。低优先级进程(友好进程,a nice progress)只有在其他更高优先级的进程使用完处理器后才能够获得处理器的时间 |
这些进程状态的后面可以带其他的字符来表示不同的特殊进程特性。可以查看ps
命令的帮助页面来获取更多的详细信息。
另一个常用的选项组合是aux
(不带前置连字符),它将输出更多的信息,如下所示:
该选项组合将会显示属于每个用户的进程信息,使用这些选项时不带前置连字符将使得命令以“BSD模式(BSD-style)”运行。ps
命令的Linux版本可以模拟多种UNIX版本中ps程序的运行方式,使用这些选项将显示更过列的信息,具体如下:
BSD模式下ps
命令输出的列标题
标题 | 含义 |
USER | 用户ID。表示该进程的所有者 |
%CPU | CPU使用百分比 |
%MEM | 内存使用百分比 |
VSZ | 虚拟耗用内存大小 |
RSS | 实际使用的内存大小。进程使用的物理内存(RAM)大小(以KB为单位) |
START | 进程开启的时间。如果数值超过24小时,那么将使用日期来显示 |
1.2、top–动态查看进程信息
虽然ps
命令可以显示有关机器运行情况的很多信息,但是它提供的只是在ps
命令被执行时刻机器状态的一个快照。要查看机器运行情况的动态视图,我们可以使用top
命令,如下所示:
top程序将按照进程活动的顺序,以列表的形式持续更新显示系统进程的当前信息(默认每3秒更新一次)。它主要用于查看系统“最高(top)”进程的运行情况,其名字也来源于此。top
命令显示的内容包含两个部分,顶部显示的是系统总体状态信息,下面显示的是一张按CPU活动时间排序的进程情况表。
系统总体状态信息包含很多有用的内容,具体如下:
行 | 字段 | 含义 |
1 | top | 程序名 |
22:21:35 | 一天中的当前时间 | |
up 39 min | 正常运行时间(uptime)。从机器最后一次启动开始计算的时间总数 | |
2 users | 有两个用户已登录 | |
load average | 负载均衡(load average)指的是等待运行的进程数;即共享CPU资源的处于可运行状态的进程数。显示的三个值分别对应不同的时间段,第一个对应的是前60秒的均值,下一个对应的是前5分钟的均值,最后一个对应的是前15分钟的均值。该值小于1.0表示该机器并不忙 | |
2 | tasks | 统计进程数即各个进程的状态信息 |
0.3% us | 0.3%的CPU时间被用户进程占用,这里指的是处于内核外的进程 | |
0.2% sy | 0.2%的CPU时间被系统进程(内核进程)占用 | |
0.0% ni | 0.0%的CPU时间被友好进程(nice)(低优先级进程)占用 | |
99.5% id | 98.3%的CPU时间是空闲的 | |
0.0% wa | 0.0%的CPU时间用来等待I/O操作 | |
4 | Mem: | 显示物理RAM(随机存取内存)的使用情况 |
5 | Swap: | 显示交换空间(虚拟内存)的使用情况 |
top程序可以接受许多键盘指令,其中最常用的有两个:一个是h,输入后将显示程序的帮助界面;另一个是q,用来退出top命令。
主流的桌面环境都提供了用来显示类似top
命令的输出信息的图形化应用程序(如Windows中任务管理器[Task Manager]的运行方式类似),但是top
命令优于图形化版本,这是因为top
命令运行地更快,而且消耗的系统资源要少得多。毕竟,系统监控程序不应该减缓正在被监控的系统的处理速度。
2、控制进程
我们以程序gedit
为例:
注意,为什么这里的shell程序提示符没有返回呢?这是因为shell正在等待该gedit程序结束,就像以前使用的其它程序一样。如果关闭gedit窗口,那么提示符将返回。
2.1、中断进程
在终端窗口,按下Ctrl-C
键将会终端(interrupt)一个程序,它意味着我们委婉地请求程序结束。按下Ctrl-C
键后,gedit窗口将关闭,shell提示符将返回。
2.2、使进程在后台运行
假设我们想要shell提示符返回,但又不终止gedit程序,那么可以通过让该程序在后台(background)运行来实现。我们可以把终端想象为有一个前台(foreground,表面上可见的内容,类似shell提示符)和一个后台(隐藏在表层下面的内容)。想要在启动程序是让该程序在后台运行,可以在命令后面加上和号字符(&)来实现。
命令执行后,将出现gedit窗口,而且shell提示符也将返回,但是同时也会打印一些有趣的数字信息。这条信息是shell的一个称为作业控制(job control)的特性表现。shell通过这条信息来显示已经启动的作业编号为1([1]),其对应的PID是19645,如果执行ps
命令,可以查看到当前运行的进程。
shell的作业控制特性特提供了一种方式来查看从该终端启动的所有作业。使用jobs命令可以得到如下列表信息。
输出结果显示存在一个编号为1的作业在运行,而且对于命令时gedit &
2.3、使进程回到前台运行
后台运行的进程不会受到任务键盘输入的影响,包括视图来中断它的Ctrl-C
键。要想使得进程返回到前台来运行,可以使用fg
命令来实现,如下所示:
我们可以通过在fg
命令后面加上百分号符号和作业编号(称为jobspec选项)来实现这个功能。如果后台只有一个任务,那么可以不带jobspec选项。这个时候按下Ctrl-C
键就可以终止gedit
命令。
2.4、停止(暂停)进程
如果我们只是想要暂停进程,而不是终止进程,那么通常需要我们将前台的进程移到后台去运行。我们为了暂停前台进程需要按下Ctrl-Z
键。
在暂停gedit命令后,我么可以通过试图改变gedit窗口的大小来确认该程序是否真正被暂停了。可以发现,该进程看起来好像死了。这个时候,我们可以使用fg
命令让进程在前台恢复运行,也可以使用bg
命令让进程移到后台运行。
如果用命令方式启动了一个图形化程序,但是忘记了在命令尾部加下“&”符号来让程序在后台运行,那么在这种情况下,把进程从前台移到后台去运行的方法将非常方便。
为什么会想要通过命令行的方式来启动一个图形化程序呢?原因有两个。首先,想要运行的程序可能不在窗口管理器的菜单中(比如gedit程序)。其次,从命令行启动程序可以看到用图形化方式启动程序所看不到的错误信息。有时候从图形菜单中启动程序,程序会启动失败。但改用命令行方式启动的话,就可以得到错误提示信息,找到问题所在。另外,一些图形化程序也包含很多有意思和有用的命令行选项。
3、信号
kill
命令通常用来“杀死”(终止)进程,它可以用来终止运行不正常的程序或者反过来拒绝终止的程序,如下所示:
我们首先在后台启动了gedit程序。shell将打印输出该后台进程的jobspec选项信息和PID信息。接着,我们使用kill
命令,并且指定想要终止进程的PID。我们也可以使用jobspec选项(例如,%1)代替PID信息来指定该进程。
这些看起来都非常简单,但是事实上,它们包含着更多的内容。kill
命令准确地说并不是“杀死”进程,而是给进程发送信号(signal)。信号是操作系统和程序通信的多种方式之一,在使用Ctrl-C键和Ctrl-Z键是已经见识过信号的作用。当终端接收到其中的一个输入是,它将发送信号到前台进程。在按下Ctrl-C键的情况下,它将发送一个称为INT
(中断,Interrupt)的信号;在按下Ctrl-Z键的情况下,它将发送一个称为TSTP
(终端暂停,Terminal Stop)的信号。反过来,程序“侦听”信号,而且在接收到信号的时候按照他们的指示进行操作。程序可以侦听信号并且按照信号指示操作的这样一特性,使得程序在接收到终止信号的时候可以保存当前正在运行的工作。
3.1、kill–发送信号到进程
kill
命令最常用的语法格式如下:
如果命令行中没有指定信号,那么默认发送TERM
(终止,Terminate)信号。kill
命令最常用来发送的信号如下所示:
信号编号 | 信号名 | 含义 |
1 | HUP | 挂起信号。该信号用来指示程序控制终端已被“挂起”。该信号的效果通过关闭终端会话的方式来实现。运行在终端上的前台程序收到该信号后将终止。该信号也被很多后台程序用来重写初始化。这就意味着,当一个后台进程接收到该信号时,它将重启并且重写读取它的配置文件。Apache Web服务器就是后台进程使用HUP信号重新初始化的一个例子 |
2 | INT | 中断信号。执行效果和在终端按下Ctrl-C键的效果一样。通常用来终止一个程序 |
9 | KILL | 杀死信号。该信号比较特殊。鉴于程序可以选择不同的方式来处理发送过来的信号,包括忽略所有的这些信号,KILL信号将不会真正意义上地被发送到目标程序。而是内核宁愿立即终止了该进程。当进程以这种方式被终止时,它将没有机会对自己进行“清理”或者对当前工作进行保存。考虑到这个原因,KILL信号只能当做其他的终端信号都执行失败的情况下的最后选择 |
15 | TERM | 终止信号。这是 |
18 | CONT | 继续运行信号。恢复之前接受了STOP信号的进程 |
19 | STOP | 暂停信号。该信号将使进程暂停,而不是终止。和KILL信号类似,该信号不会被发送给目标程序,因此它不能被忽略 |
在这个例子中,我们首先在后台启动了gedit程序,接着使用kill命令给它发送HUP信号。gedit程序将终止,shell的输出信息表明这个后台进程以及接收了一个挂起信号。你也许需要多敲几次Enter键才能看到这条输出信息。
注意:可以通过信号编号或者信号名来指定信号,其中包含带有SIG前缀的信号名;此外可以使用jobspec选项代替PID信息。
和文件一样,进程也有所有者,只有进程的所有者(或者超级用户)才能使用kill
命令来给它发送信号。除了上面列出的一些经常被系统使用的信号,进程还有很多别的信号:
信号编号 | 信号名 | 含义 |
3 | QUIT | 退出信号 |
11 | SEGV | 段错误信号。如果程序非法使用内存空间,即程序试图在没有写权限的空间执行写操作,那么系统将发送该信号 |
20 | TSTP | 终端暂停信号。在按下Ctrl-Z键时终端发出该信号。与STOP信号不同的是,TSTP信号有程序接收,但是程序可以选择忽略该信号 |
28 | WINCH | 窗口改变信号。当窗口改变大小时,系统将发送该信号。类似top和less的一些程序将会对该信号作出响应,重新绘制视图来适应新的窗口大小 |
如果想要查看很多的信号,使用如下命令将显示完整的信号列表:
3.2、killall–发送信号给多个进程
通过使用killall
命令,我们可以给指定程序或者指定用户名的多个进程发送信号,一般语法格式如下:
在后台启动了两个gedit程序,然后终止它们。
注意:和kill
命令一样,你必须具有超级用户权限,才能够使用killall
命令给不属于自己的进程发送信号。
4、更多与进程相关的命令
由于进程监控是一项重要的系统管理任务,所以存在很多命令用来为它服务:
命令 | 描述 |
pstree | 以树状的模式输出进程列表,该模式显示了进程间的父/子关系 |
vmstat | 输出系统资源使用情况的快照,包括内存,交换空间和磁盘I/O。如果想要持续查看输出,可以在命令后面加上一个间隔时间(以秒为单位),命令将按照间隔时间来动态更新显示的内容(比如:vmstat 5)。按下Ctrl-C可以终止输出 |
xload | 用来绘制显示系统时间负载情况图形的一种图形化界面程序 |
tload | 类似于xload程序,但是图形是在终端上绘制。按下Ctrl-C键终止输出 |