对话 UNIX,第 8 部分: UNIX 进程( 二 )


例如 , 如果您想查看您拥有的所有进程 , 键入 ps -w --user username :$ ps -w --user mstreicher您可以使用 ps -a -w -x 查看完整的进程列表 。(ps 命令的格式和特定的标志随各个 UNIX 版本而有所差异 。请参阅系统的联机文档 , 以查找具体的说明 。) -a 是选择 tty 设备上运行的所有进程;-x 则可进一步选择与 tty 无关的所有进程 , 通常包括所有的永久系统服务 , 如 Apache HTTP server、cron 工作调度程序等等;-w 则以加宽的格式显示内容 , 在查看命令行或与每个进程相关的应用程序完整路径名时很有用 。
ps 具有丰富的功能 , 某些版本的 ps 甚至允许您自定义输出 。例如 , 下面就是一个有用的自定义进程列表:
$ ps --user mstreicher -o pid,uname,command,state,stime,time
 PID USER COMMAND S STIME TIME
14138 mstreic sshd: mstreicher S 09:57 00:00:00
14139 mstreic -bashS 09:57 00:00:00
14937 mstreic ps --user mstrei R 10:23 00:00:00-o 根据各列名称的顺序对输出进行格式化 。pid、uname 和 command 分别指进程 ID、用户名和命令 。state 代表进程的状态 , 如正在睡眠 (S) 或运行 (R) 。(稍后将对进程状态进行更详细的说明 。)stime 显示命令的开始时间 , time 则显示该进程占用了多少 CPU 时间 。
进程从哪里来?
在 Unix 中 , 某些进程会从系统启动到关机的时间里一直运行 , 但大多数进程都会随任务的开始和完成而迅速地出现和消失 。有时 , 某个进程可能会“早夭“ , 甚至会“暴死(比如在系统崩溃时) 。新的进程是从哪里来的呢?
每个新的 UNIX 进程都是某个现有进程的产物 。另外 , 每个新进程(不妨将其称为“子进程)是对“父进程的克隆体(至少有一瞬间是如此) , 直到“子进程继续独立执行为止 。(如果每个进程都是某个现有进程的后代 , 那么不免会有一个疑问:“第一个进程是从哪里来的?请参阅下面的侧栏以寻找答案 。)
鸡和蛋 某些争论是经久不息的:生存还是毁灭?可口可乐还是百事可乐?PC 还是 Mac?当然 , 还有一个古老的悖论 , “鸡生蛋 , 还是蛋生鸡?
【对话 UNIX,第 8 部分: UNIX 进程】如果每个新的 UNIX 进程都是某个现有的、正在运行的进程的后代 , 那么第一个进程是从哪里来的?答案是:UNIX 内核在系统启动序列中产生了第一个进程 。
第一个进程被恰如其分地称为 init , 所有其他系统进程的亲缘关系最终都可以追溯到 init 。实际上 , init 的进程编号是 1 。如果您要查看 init 的状态 , 可键入 ps -l 1:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S010 0 680 -373 select ?0:02 init [2]正如您所看到的 , init 的所有者 (UID) 是 0 (root) 。和系统中所有其他进程不同的是 , init 没有父进程 , 它的父进程 ID (PPID) 为 0 。图 1-4 详细说明了进程的产生过程:
在图 2 和图 3 中 , 进程 A (Process A) , 正在运行一个由蓝色方框表示的程序 。它运行编号为 10 , 11 , 12…的指令 。进程 A 有属于自己的数据、程序的副本、打开的文件集 , 以及自己的环境变量集 , 当进程 A 刚出现时 , 会对它们进行初次捕捉 。
图 2. 进程 A 运行代码
在 Unix 中 , fork() 系统调用(之所以有这个名称 , 是因为它是一个调用或请求 , 要求操作系统进行协助)被用来产生新的进程 。当程序 A (Program A) 执行指令 13 (Instruction 13) fork() 时 , 系统会立即创建进程 A 的一个精确克隆版本 , 并将其命名为进程 Z (Process Z) 。Z 具有和 A 相同的环境变量、相同的内存内容、相同的程序状态 , 打开的文件也一样 。图 3 显示的是进程 A 生成进程 Z后 , 进程 A 和 Z 的状态 。

推荐阅读