2次使用fork避免产生僵尸进程和不去处理SIGCHLD信号

1.如下代码所示

#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc,char *argv[])
{
        pid_t child = fork();

        if( child == -1 ) { //error
                printf("\nfork child error.");
                exit(0);
        } else if(child == 0){
                //exit(0);
                if ((child = fork()) < 0)
                        printf("fork error\n");
                else if (child > 0)
                {
//                      sleep(3);
                        exit(0);
                }
                sleep(5);
                printf("second child,parent pid %d\n",getppid());
                exit(0);
        }
//      sleep(3);
        if (waitpid(child,NULL,0) != child)
                printf("waitpid error\n");
        sleep(10);
        exit(0);
        //sleep(600);

}

1个终端使用gcc -g test.c -o test 生成test程序后,准备执行。

另1个终端不断敲击命令ps lfx | grep test,其中第3列显示pid,第4列显示ppid。

可以看到另1个终端显示:

0 0 28787 20574 20 0 3920 340 hrtime S+ pts/1 0:00 | \_ ./test
0 0 28792 20817 20 0 103248 828 pipe_w S+ pts/2 0:00 \_ grep test
1 0 28789 1 20 0 3920 140 hrtime S+ pts/1 0:00 ./test

其中第3行为我们第二次fork的子进程,其ppid已为1(即init进程)

第1行的test进程为主进程在sleep(10),达到了咱们的目的。

2.这里主要探讨下waitpid在这里的用法

作用:回收第1个fork产生的子进程,这里的代码显示这个子进程产生后马上调用exit。

3.疑惑:fork函数后父子进程的先后执行顺序不定,waitpid总能成功收回吗?

在这里做2个实验,

第一次把代码中第20行sleep(3);解除注释,运行,观察结果。(主进程waitpid执行后产生僵尸进程)

第二次把代码中第27行sleep(3);解除注释,运行,观察结果。(主进程waitpid执行前产生僵尸进程)

可见2次实验中最后都没有僵尸进程,说明都成功收回了。

第2次实验中僵尸进程大概存在了3秒左右,是由于第27行的sleep(3).

可见次代码中主进程的waitpid总能把第一次fork的子进程成功收回。

时间: 2024-11-07 02:58:03

2次使用fork避免产生僵尸进程和不去处理SIGCHLD信号的相关文章

linux 在线程中fork无法清除僵尸进程。

在某些线程库中,线程中通过fork创建的子进程无法通过wait或waitpid清理掉,原因是线程里面屏蔽的SIG_CHLD信号. 可在线程主函数加入以下代码解决: signal(SIGCLD, SIG_IGN); /* don't need to wait child process */ 忽略这个信号后的作用是,告诉系统不关心子进程的执行返回值,系统可以自动回收所有结束的子进程.

僵尸进程

In UNIX System terminology, a process that has terminated,but whose parent has not yet waited for it, is called a zombie. 在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程. 但是如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程, 因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进

关于如何有效避免僵尸进程的一种探索。(动手写自己的http服务器)

关于如何避免僵尸进程.其实方法很多.有很多现成的解决方案.这里给出一个简单的方案.以及背后思考的过程. 设想一种最简单的http服务器: 伪代码: 当接收到一个tcp请求的时候. fork 一个子进程去做工作. 主进程依旧在监听下面要来的请求. 这个模型实际上会导致.因为fork出来的子进程没有回收,并且父进程一直存在没有结束.导致越来越多的僵尸进程出现. 都知道子进程结束的时候会发一个sigchld信号给父进程.于是改进成增加一行代码: signal(SIGCHLD,deal_signal);

[转] linux下的僵尸进程处理SIGCHLD信号

什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些 信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间,所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息. 而僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程. 任何一个子进程(init除外)在exit后并非马上就消失,而是

linux下的僵尸进程处理SIGCHLD信号

什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间,所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息. 而僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程. 任何一个子进程(init除外)在exit后并非马上就消失,而是留

linux --&gt; 孤儿进程与僵尸进程

孤儿进程与僵尸进程 一.介绍 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程.孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作. 僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中.这种进程称之为僵死进程. 二.危害 1.僵尸进程的危害 unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息,这种机

linux处理僵尸进程

由来 在linux下,如果一个进程终止,内核会释放该进程使用的所有存储区,关闭所有文件句柄等,但是,内核会为每个终止子进程保留一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间.当终止子进程的父进程调用wait或waitpid时就可以得到这些信息 僵尸进程指:一个进程退出后,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程 任何一个子进程(init除外)在退出后并非马上就消失,而是留下一个称为僵尸进程的数据结构,等待父进程处理.这是

进程控制、孤儿进程和僵尸进程

一.进程控制 1.进程标识 1.操作系统里每打开一个进程都会创建一个进程ID,这是唯一标识进程的编号,即PID. 2.PID 在任何时刻都是唯一的,但是可以重用.当进程终止并被回收以后,其 PID 就会被系统回收 3.进程的 PID 由系统内核根据延迟重用算法生成,以确保新进程的 PID 不同于最近终止进程的 PID. 4.进程PID的最大值是有限的(因系统的不同而不同),需要及时回收 2.特殊进程 0 号进程:通常是调度进程,常常被称为交换进程(swapper).该进程是内核的一部分,所有进程

如何防止僵尸进程的产生之fork两次

#include<stdio.h> #include<sys/types.h> #include<sys/wait.h> #include<unistd.h> #include<signal.h> int main( void ) { pid_t pid; if( (pid=fork()) < 0 ) { fprintf(stderr, "main 1 fork err!\n"); return 0; } else if