咏月东南 2019-11-10
这里讲解几个在 Linux 操作系统上使用 fork 系统调用。(不定期更新)
一、atexit 函数
void cleanup(void) {
printf("Cleaning up\n");
}
void fork6()
{
atexit(cleanup); printf("L0"); fork(); printf("L1");
exit(0);
}运行结果:

int atexit(void (*func)(void)) 函数,当进程正常结束时才会调用 atexit 中的 func 方法,无论你将 func 函数写在哪里。
二、回收子进程
当一个进程由于某种原因终止时,内核并不立即将其从系统中清除。而是会保持在终止的状态等待父进程回收,这称之为 ”僵死进程“ 。当父进程回收已终止的进程时,内核将子进程的退出状态传递给父进程,然后抛弃已终止的进程。至此,该进程不存在。
如果一个父进程终止了,内核会安排 init 进程为它的孤儿进程的养父。
在 64 位系统中,养父的进程号一般不为 1 ,而是一个随机进程号,但是这个进程的 cmd 都是 ”/lib/systemd/systemd --user"/
(使用 ps -ef 命令查看)

1. 子进程先结束,父进程循环挂起。儿子进程正常回收。
void fork7()
{
if (fork() == 0) {
/* Child */
printf("Terminating Child, PID = %d\n", getpid());
exit(0);
} else {
printf("Running Parent, PID = %d\n", getpid());
while (1)
; /* Infinite loop */
}
}运行结果:

2. 父进程先结束,子进程陷入循环挂起。
void fork8()
{
if (fork() == 0) {
sleep(1);
/* Child */
printf("Running Child, PID = %d\n", getpid());
printf("Running Child, PPID = %d\n",getppid());
while (1)
; /* Infinite loop */
} else {
printf("Terminating Parent, PID = %d\n", getpid());
exit(0);
}
}运行结果:

第二个代码样例中,父进程比子进程先结束运行,此时子进程成为孤儿进程,被收养。养父为前面介绍的进程。
3. 下面有一道对回收子进程有一定参考性的题。
int main(){
int pid1, pid2, pid3, pid4, pid5;
printf("1号进程开始\n");
//得到第一个进程的pid
pid1 = getpid();
printf("PID1 = %d\n", pid1);
//创建第二个进程
pid2 = fork();
if (pid2 == 0)
{
printf("2号进程开始\n");
printf("PID2 = %d, Parent PID = %d\n", getpid(), getppid());
printf("2号进程结束\n");
//exit退出
exit(0);
}
//创建第三个进程
pid3 = fork();
if (pid3 == 0)
{
printf("3号进程开始\n");
printf("PID 3= %d, Parent PID = %d\n", getpid(), getppid());
//在3号进程里面 创建第4个进程
pid4 = fork();
if (pid4 == 0)
{
printf("4号进程开始\n");
printf("PID 4= %d, Parent PID = %d\n", getpid(), getppid());
//sleep 3 second 等待3号进程结束,自己变成孤儿进程
sleep(3);
printf("4号进程结束\n");
exit(0);
}
//在3号进程里面,创建第5个进程
pid5 = fork();
if (pid5 == 0)
{
printf("PID 5= %d, Parent PID = %d\n", getpid(), getppid());
printf("5号进程开始\n");
//sleep 3 second 等待3号进程结束,自己变成孤儿进程
sleep(3);
printf("5号进程结束\n");
exit(0);
}
//等待子进程的结束 便于观察pid之间的关系
printf("3号进程结束\n");
exit(0);
}
//等待子线程的结束
printf("1号进程结束\n");
return 0;
}
————————————————
版权声明:本文为CSDN博主「张谷谷」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Paulhappy/article/details/50984888编译代码使用下列命令
$ gcc -o process.out processes.c -lpthread
运行结果如下:

该程序的进程图如下:
