进程是操作系统上非常重要的概念,所有系统上面跑的数据都会以进程的类型存在。在 Linux 系统当中:触发任何一个事件时,系统都会将它定义成为一个进程,并且给予这个进程一个 ID,称为 PID,同时根据触发这个进程的用户,给予这个 PID 一组有效的权限设置。
进程是什么样的
程序运行起来后,我们看不到也摸不着。因此 Linux 为我们提供了一系列方便的命名来查看正在运行的进程。首先是 ps 命令,比如 ps -l
命令能查看当前 bash 下的相关进程全部信息。如下:$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 2552 2538 0 80 0 - 1945 wait pts/0 00:00:00 bash
0 S 1000 9352 2552 0 80 0 - 1926 wait pts/0 00:00:00 bash
0 R 1000 9478 9352 0 80 0 - 1598 - pts/0 00:00:00 ps
另外,我们还可以用 pstree
命令来显示整棵进程树。
可以看到这里 init 进程是所有进程的根节点,使用ps
命令还能看到 init 的 PID 为 1 。当Linux启动的时候,init 是系统创建的第一个进程,这一进程会一直存在,直到我们关闭计算机。所有其他的进程都是由 init 进程衍生出来的。
父进程 & 子进程
上面提到所谓的“衍生出来的进程”正是 Linux 的父子进程的概念。当我们登录系统后,会取得一个 bash shell,然后我们利用这个 bash 提供的接口去执行另一个命令,例如 bash
或者 ps
等。那些另外执行的命令也会被触发成为 PID,那个后来执行的命令产生的 PID 就是“子进程”,而原本的 bash 环境下,就称为“父进程”了。
老进程成为新进程的父进程(parent process),而相应的,新进程就是老的进程的子进程(child process)。一个进程除了有一个PID之外,还会有一个PPID(parent PID)来存储的父进程 PID。如果我们循着 PPID 不断向上追溯的话,总会发现其源头是 init 进程。所以说,所有的进程也构成一个以 init 为根的树状结构。
我们使用 ps -o
命令来看一看现有的进程。
$ ps -o pid,ppid,comm |
我所做的操作是在原来的 bash shell 中执行了 bash 命令,然后又执行了 ps 命令。我们可以看到,第二个进程 bash 是第一个进程 bash 的子进程,而第三个进程ps是第二个进程的子进程。
fork & exec
当计算机开机的时候,内核(kernel)只建立了一个 init 进程。Linux kernel 并不提供直接建立新进程的系统调用。剩下的所有进程都是 init 进程通过 fork 机制建立的。新的进程要通过老的进程复制自身得到,这就是 fork。fork 是一个系统调用。进程存活于内存中。每个进程都在内存中分配有属于自己的一片空间 (内存空间,包含栈、堆、全局静态区、文本常量区、程序代码区)。当一个程序调用 fork 的时候,实际上就是将上面的内存空间,又复制出来一个,构成一个新的进程,并在内核中为该进程创建新的附加信息 (比如新的 PID,而 PPID 为原进程的 PID)。此后,两个进程分别地继续运行下去。新的进程和原有进程有相同的运行状态(相同的变量值,相同的指令…)。我们只能通过进程的附加信息来区分两者。
程序调用 exec 的时候,进程清空自身的内存空间,并根据新的程序文件重建程序代码、文本常量、全局静态、堆和栈(此时堆和栈大小都为 0),并开始运行。
工作管理
这个工作管理(job control)是用在 bash 环境下的,也就是说,当我们登录系统取得 bash shell 之后,在单一终端机下可以同时进行多个工作的行为管理。
假如我们只有一个终端,因此在可以出现提示符让你操作的环境就成为前台(foreground),至于其他工作就可以放在后台(background)去暂停或运行。
工作管理的意义在于将多个工作囊括在一个终端,并取其中的一个工作作为前台,来直接接收该终端的输入输出以及终端信号。 其他工作在后台运行。
直接将命令丢到后台执行:
&
$ping localhost > log
此时终端显示:
[1] 9800
括号中的 1 表示工作号,而 9800 为 PID
将目前的工作丢到后台中“暂停”:
[ctrl]+z
在vim的普通模式下,按下
[ctrl]+z
的组合键[ ]+ 已停止 vim ~/.bashrc
查看目前的后台工作状态:
jobs
其各个参数的含义如下
-l :同时列出PID的号码
-r:仅列出正在后台run的工作
-s:仅列出在后台stop的工作例如我们执行
$ jobs -l
[1]- 9800 运行中 ping localhost > log &
[2]+ 9905 停止 vim ~/.bashrc能看到目前有多少个工作在后台中,并且能看到这些工作的 PID。紧跟在 job number 后面的
+
代表最近放到后台的工作,-
代表最近最后第二个放到后台的工作,直接执行fg
的话会先取+
的将后台工作拿到前台来处理:
fg %jobnumber
当我们运行第一个命令后,由于工作在后台,我们无法对命令进行输入,直到我们将工作带入前台,才能向 cat 命令输入。在输入完成后,按下 CTRL+D 来通知 shell 输入结束。
让工作在后台下的状态变成运行中:
bg %jobnumber
管理后台工作中的工作:
kill
信号可以通过 kill 传递给进程,信号值以下三个比较重要。
-1 重新加载 (SIGHUP)
-9 立刻删除 (SIGKILL)
-15 正常终止(SIGTERM)可以使用
或者
的方式来发送给工作。上面的两个命令,一个是发送给信号给 PID 9800 ,一个是发送信号值给工作号1,两者等价。
监控进程的变化:
top
top 是一个很不错的程序查看工具,但不同于 ps 的静态结果输出,top 可以持续监测整个系统的进程工作状态,而且功能非常丰富,可以在 top 中输入?
查看更多功能按键。常用的有P
以CPU使用资源排序,M
以物理内存使用排序。常用的参数有
-d
可以修改进程界面更新的秒数,-p
可以指定某些个 PID 来进行查看监测。
参考资料
-EOF-