僵尸进程和处理

来源:互联网 发布:docker sql server 编辑:程序博客网 时间:2024/05/16 09:54
//代码参考:http://www.cnblogs.com/Anker/p/3271773.html

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    pid_t pid;
    pid = fork();
    if( pid < 0)
    {
        perror("fork error:");
        exit(1);
    }
    else if (pid == 0)
    {
        printf("I am child process\n");
        exit(0);
    }

    printf("i am the father\n");
    sleep(2);

    system("ps -o pid,ppid,tty,state,command");

    printf("the father exit\n");

    return 0;
}

代码解读:
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到。这种机制就是: 在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放。 但这样就导致了问题,如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。

//僵尸进程解决方案:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>

static void signHandler(int sign);


int main()
{
    pid_t pid;

    signal(SIGCHLD, signHandler);
    pid = fork();
    if( pid < 0)
    {
        perror("fork error");
        exit(1);
    }
    else if( pid == 0)
    {
        printf("i am child process, pid id %d \n", getpid());
        exit(0);
    }

    printf(" I am father process ^_^\n");

    sleep(2);
    system("ps -o pid,ppid,state,tty,command");
    printf("father process exit\n");
    return 0;
}

static void signHandler(int signo)
{
    pid_t pid;
    int stat;

    while( (pid = waitpid(-1, &stat, WNOHANG)) > 0 )
        printf("child %d terminated \n", pid);
}

代码解读:子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程。

2 signal(sgn, func);
执行了signal()调用后,进程只要接收到类型为sign函数第一个参数的信号,不管其正在执行程序的哪一部分,
就立即执行func()函数。当func()函数执行结束后,控制权返回进程被中断的那一点继续执行。

3 waitpid 函数
pid_t waitpid(pid_t pid, int * status, int options)

1 pid > 0  只等待进程 pid 的子进程
2 pid = -1  等待任何一个子进程退出

options: WNOHAND (wait no hang), 即使没有子进程退出,立即返回,不再等待

返回值: 当正常返回, 子进程的pid;
设置 WNOHANG, 调用时发现没有子进程可退,return 0;
出错 返回 -1
0 0
原创粉丝点击