所谓进程等待,其实很简单。前面我们说过可以用fork创建子进程,那么这里我们就可以使用wait函数让父进程等待子进程运行结束后才开始运行。注意,为了证明父进程确实是等待子进程运行结束后才继续运行的,我们使用了sleep函数。但是,在linux下面,sleep函数的参数是秒,而windows下面sleep的函数参数是毫秒。
下面对下面的程序进行解释:
1,fork():正如上一节讨论的,这个是父进程创建子进程,返回值小于0就表示失败;
创建成功的话,也会返回2两次,一次是子进程(返回值是0),一次是父进程的(返回值>0);
但是到底是谁先返回,并不一定,所以就存在问题了?
如果是父进程先返回,那么父进程的子进程的控制权就交给了init进程(下面在介绍),没问题,好;
但是如果是子进程先返回,而父进程返回后又没有采取任何的子进程资源回收(回收什么?下面再说),那这个子进程就成为了僵尸进程,
他占用了进程号(系统里分配的进程号是有限的),如果父进程返回后,并没有结束,而是在此创建这样的字进程等过程,那么久而久之,
系统就会出现崩溃的迹象;
2,回答上面的问题:
问题1:init进程是什么?http://www.baike.com/wiki/init%E8%BF%9B%E7%A8%8B
linux在启动时,必须启动的第一个程序或者叫进程,此进程启动时,会读取/etc/inittab等配置文件里的参数,来启动运行级别,登入 界面程序的启动等一系列工作,且监听有父进程结束后,子进程没有退出的情况,此时,init就会成为该子进程的父进程,从而实现
子进程资源的释放;
问题2:子进程到底要释放什么资源?
在子进程返回或者使用exit()退出时,内核释放该进程所有的资源,包括打开的文件,占用的资源等,但是还保留了一些数据结构 (包括进程号,运行时间,退出时状态),此时子进程成了僵尸进程,之所以有这些,是为了让父进程能通过调用函数而获取子进程的这些信息。所以为了避免僵尸进程,在子进程退出时,父进程要进行判断,具体用wait()或者waitpid()函数进行等待,此时主进 程挂起,但是子进程生于的资源会得到释放,譬如说子进程id号;另外一种方法是,主进程里用signal函数SIGCHLD的处理函数,在处 理函数里调用wait();还有方法:父进程signal(SIGCHLD,SIG_IGN),表示父进程不关心子进程的这些信息,子进程结束时,交由内核回 收资源;另外的方法如,fork()两次,父进程fork()后,子进程在fork(),此时的孙进程就会由init接受;但是子进程还是要父进程处理;
问题3: wait(int *status): 参数是指向子进程退出状态的一个代码;比如子进程exit(4). status就指向3;如果不关心,此参数可设为NULL;
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- int main(int argc, char* argv[])
- {
- pid_t pid;
- pid = fork();
- if(0 == pid)
- {
- printf("This is child process, %d\n", getpid());
- sleep(5);
- }
- else
- {
- wait(NULL);
- printf("This is parent process, %d\n", getpid());
- }
- return 1;
- }
- [root@localhost fork]# ./fork
- This is child process, 2135
- This is parent process, 2134
下面通过例子来实战一下我们刚刚学到的内容:
/* wait2.c */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{ int status;
pid_t pc, pr;
pc = fork();
if ( pc < 0) /* 如果出错*/
printf("error occured.\n");
else if ( pc == 0 ) /* 子进程*/
{
printf("This is child process with pid of %d.\n", getpid());
exit(3); /* 子进程返回3 */
}
else /* 父进程*/
{
pr = wait(&status);
if ( WIFEXITED(status) ) /* 如果WIFEXITED返回非零值*/
{ printf("The child process %d exit normally.\n", pr);
printf("the return code is %d.\n", WEXITSTATUS(status));
}
else /* 如果WIFEXITED返回零 */
printf("The child process %d exit abnormally.\n", pr);
}
编译并运行: $ gcc wait2.c -o wait2 $ ./wait2 This is child process with pid of 1538. the child process 1538 exit normally. the return code is 3. 父进程准确捕捉到了子进程的返回值3,并把它打印了出来。