1 进程与程序
在Linux系统中,执行一个程序或命令就可以触发一个进程,系统会给予这个进程一个ID,称为PID,同时根据触发这个进程的用户与相关属性关系,基于这个PID一组有效的权限设置。如下图所示(图片来自《鸟哥的Linux私房菜》[1]):
举个常见的例子,我们要操作系统的时候通常是利用ssh连接程序或直接在主机上登录,然后获取shell。默认的shell是bash,对应的路径为/bin/bash
,那么同时间的每个人登录都是执行/bin/bash
,不过每个人获取的权限不同,如下图所示:
也就是说,当我们的登录并执行/bin/bash
程序时,系统已经给了我们一个PID,这个PID就是根据登陆者的UID/GID(/etc/passwd
)而来,而所谓用户的权限就是这个bash进程的权限。当这个进程执行其它作业时,比如我们在shell中执行touch
命令时,这个进程触发出来的其它进程也会沿用这个进程的相关权限。
我们对程序与进程做一个总结:
- 程序(program):通常为二进制程序,存储在存储媒介中(如磁盘等),以物理文件的形式存在。
- 进程(process):程序被触发后,执行者的权限与属性、程序的代码与所需数据等都会被加载到内存中,操作系统给予这个内存中的单元一个标识符(PID),可以说进程就是一个正在运行中的程序。
进程彼此之间是有关系的。从下图来看,连续执行两个bash后,第二个bash的父进程就是前一个bash,通过Parent PID(PPID)可获取其父进程的PID:
此外,子进程可以获取父进程的环境变量。
下面这个例子我们会展示子进程和父进程的关系。我们在当前的bash环境下,再触发一次bash,并用ps -l
命令查看进程相关的输出信息,
bash-3.2$ ps -l
UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD
501 9892 9827 4006 0 31 0 408650672 1968 - S 0 ttys001 0:00.01 /bin/bash
501 9905 9892 4006 0 31 0 408657840 2736 - S 0 ttys001 0:00.01 /bin/bash
可以看到第一个bash的PID和第二个bash的PPID都是9892,这是因为第二个bash是来自第一个所产生的。
很多常常会发现,“咦,我们们将有问题的进程关闭了(比如Ctrl+C
杀掉),怎么过一阵子它又自动产生了?而且新产生进程的PID还与原先不同这是怎么回事呢?”如果不是crontab计划任务的影响,那么肯定有一个父进程存在,所以我们杀掉子进程后,父进程又会主动再生成一个。那怎么办呢?“擒贼先擒王”。我们用ps auxf
找出那个父进程,然后将它杀掉即可(后文会提到)。
fork and exec:进程调用的流程
子进程和父进程之间的关系比较复杂,最大的复杂点在于进程之间的调用。Linux程序的调用通常称为fork-and-exec流程。进程都会借由父进程以复制(fork)的方式产生一个一模一样的子进程,然后被复制出来的子进程再以exec的方式来执行时机要执行的代码,最终就成为一个子进程。整个流程有点像下面这张图:
- 系统先以fork的方式复制一个与父进程相同的临时进程,这个进程与父进程唯一的差别就是PID不同,但这个临时进程还会多一个PPID参数。
- 然后临时进程开始以exec的方式加载实际要执行的进程。以上图来讲,新的程序名称为
qqq
,最终子进程的进程代码就会变成qqq
了。
系统或网络服务:常驻在内存里的进程
一般的Linux命令(如ls
、touch
、rm
等)都是执行完就结束,也就是说该项命令被触发后所产生的PID很快就会被终止,那么有没有一直在执行的进程呢?
当然有,我们把在后台启动并一直持续不断地运行,也即常驻在内存当中的进程称为守护进程(daemon)。常见的服务包括系统本身所需要的服务(例如crond、atd、rsyslogd等)和负责网络连接的服务(例如apache、named、postfix、vsftpd等)。网络服务比较有趣的地方在于,它会启动一个可以复杂网络监听的端口(port),以提供外部客户端(client)的连接请求。
PS1:在Linux系统中,一般daemon类型的进程都会在文件名后面加上d。
PS2:“守护进程”这个概念由麻省理工学院MAC项目的程序员发明。费南多·柯巴托于1963年在MAC项目任务。根据他的说法,他的团队最早采用daemon这个概念,其灵感来源于麦克斯韦妖——一种物理学和热力学中虚构的介质,能帮助排列分子。他对此表示:“我们别出心裁地开始使用daemon这个词来描述后台进程,它们不知疲倦地处理系统中的杂务。”Unix系统继承了这个术语。作为一种在后台起作用的超自然存在,麦克斯韦妖与古希腊神话中的代蒙一致[2]。关于麦克斯韦妖的更多有趣信息可以参见梅拉妮·米歇尔的《复杂》[3]一书。
2 进程管理
想要查看系统上正在运行中的进程,可以利用静态的ps
或者是动态的top
命令,还可以利用pstree
来查看进程树之间的关系。
ps:将某个时间点的进程运行情况撷取下来
ps aux
可查看系统中所有的进程(注意,没有-
号):
~/Orion-Orion # ps -aux root@qi
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4504 48 pts/0 Ss 2022 0:01 sh /root/start.sh
root 7 0.0 0.0 65520 420 ? Ss 2022 0:07 /usr/sbin/sshd
root 8 0.0 0.0 20052 264 pts/0 S+ 2022 0:00 /bin/bash
...
root 39717 0.1 0.0 93648 7608 ? Ss 08:40 0:02 sshd: root@notty
root 39727 0.0 0.0 9752 2924 ? Ss 08:40 0:00 bash
root 40140 0.5 0.0 95296 9220 ? Rs 08:54 0:02 sshd: root@notty
root 40150 0.0 0.0 9752 2832 ? Ss 08:54 0:00 bash
ps -l
则可以仅查看自己的bash相关的进程:
~/Orion-Orion # ps -l root@qi
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 0 42331 41909 0 80 0 - 5015 wait pts/312 00:00:00 bash
0 R 0 42379 42331 0 80 0 - 6920 - pts/312 00:00:00 ps
我们可以看到,系统整体运行的进程是非常多的,但使用ps -l
仅会列出与你的操作环境(bash)有关的进程,即最上层的父进程会是你自己的bash而没有扩展到systemd
(后续会介绍)这个进程中。我们接下来来看看ps -l
显示出来的数据有哪些?
- F:表示这个进程标识(process flags),说明这个进程的权限,常见号码有:
- 若为4表示此进程的权限为root。
- 若为表示此进程仅执行复制(fork)而没有实际执行(exec)。
- 若为0表示进程标识没有设置。
- S: 代表