本章介绍在Unix系统中对进程的控制,包括创建进程、执行程序、进程中止等。
还介绍了进程的各种属性,如进程ID。
1.进程标识符(Process identifier)
每个进程有一个唯一的非负标识号,进程ID。
几个特殊的进程:
ID=0的进程:通常是调度进程Scheduler Process,或者叫Swapper。它是内核的一部分,作为系统进程运行
ID=1的进程:通常是init进程,程序位于/sbin/init,负责启动Unix系统。 init通过读取系统初始化文件(/etc/rc*)将系统启动到指定的运行级别。
init进程不会结束。如果父进程在子进程终止之前就结束了,则该父进程的所有子进程的父进程ID被修改为1,即init进程,以保证所有进程都有父进程。
2.fork函数
Unix系统产生新进程的唯一方法:调用fork()函数
#include \
#include \
pid_t fork(void); return 0 in child , process ID of child in parent, -1 on error
3.文件共享
由于fork函数复制了父进程的文件打开表给子进程,故具有父子关系的进程将共享打开文件。见下图
javascript:window.open(this.src);" style="CURSOR: pointer" onload="return imgzoom(this,550)">
注意与独立进程间(不是父子关系进程)文件共享的区别!
父子进程共享了文件表(上图中间一栏),所以不论是谁修改了文件,文件偏移量的修改对双方都是有效的。
独立进程间的文件共享是共享的V-node结构(上图第三栏),所以进程间拥有各自不同的当前文件偏移量,这点注意。
3。vfork函数
vfork和fork的功能基本一致,均是创建创建一个新进程。但是有两点不同:
a) vfork创建的新进程专门用于执行新的程序,所以它不会全部复制父进程地址空间内的所有信息给子进程。通常调用vfork后,子进程将紧跟着调用exec
b) vfork保证子进程首先运行,父进程挂起,直至子进程调用exec或exit,父进程才重新运行
4。wait 和 waitpid函数
当一个进程结束的时候,内核将发送一个SIGCHLD信号给其父进程。下面两个函数用于父进程等待子进程结束
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
both return process ID if OK, 0 and -1 on error
参数说明:
int *statloc用于存储结束进程的终止状态。但如果我们不关心子进程的结束状态,可以给null指针。
pid_t pid : waitpid指定等待进程的ID号。
若指定pid=-1,则其功能与wait一致,相当于无阻塞版的wait
两者区别:
wait将阻塞调用进程,直至该进程任何一个子进程结束。但如果该进程有僵尸子进程,则wait函数将立即返回,statloc存放该僵尸进程的终止状态。
(僵尸进程,zombie process,指已经结束的进程,但其父进程并未获取其终止状态,释放资源等操作的进程)
waitpid等待process id为pid的子进程结束。即利用该函数可以扑获指定的进程结束的状态,但是并不阻塞调用者
5。exec函数
前面提到vfork,创建的子进程用于执行新的程序,共有六种形式的exec
记忆方法:
l : 表示使用参数列表(list)
e:表示使用新的环境变量,不从当前继承
p: 表示使用文件名,并从PATH环境进行搜索
6. System函数
利用System函数可以在程序中方便的调用shell命令.
例如,想向一个文件中保存当前时间,可以很容易实现 System("date > file");
System函数原形为 :
int system(const char *cmdstring);
system函数由fork,exec,waitpid来实现