网络编程(32)—— linux中销毁僵尸进程的四种方法

一、wait函数


函数原型:
pid_t wait(int *status);
描述:
wait可以回收任意一个僵尸进程,只要系统中存在僵尸进程,调用一次wait,就会回收一个僵尸进程。
参数说明:
  status - 当子进程结束之后,其进入僵尸进程状态。其状态变化信息被操作系统放置在内存中某一处位置,而status就是这处位置的指针,通过调用wait函数可以获取这部分位置的数据。
获取到数据之后,通过一系列宏可以获取目前操作系统的状态。如:
WIFEXITED(*status)可以判断该进程是否正常结束(main函数通过return或者exit结束),若正常结束返回true,否则返回false。
WEXITSTATUS(*status)用来获取进程正常结束时main函数的返回值,前提是WIFEXITED(status)返回true。
返回值:
返回被结束僵尸状态进程的进程ID。
举例:
int main()
{
    pid_t pid;
    int status;
    pid=fork();
    if(pid==0)
    {
        exit(10);
    }
    else
    {
        pid = wait(&status);
        if(WIFEXITED(status))
        {
            printf("process %d exited,return value = %d\n",pid,WEXITSTATUS(status));
        }
    }
    return 0;
}


缺点:
wait()函数为阻塞函数,也就是说如果操作系统中无僵尸进程的话,程序会一直在wait()处等待,直到出现僵尸进程。


二、waitpid函数


函数原型:
pid_t waitpid(pid_t pid, int *status, int options);
描述:
waitpid()也是用来回收一个僵尸进程,与wait()不同的是,它是非阻塞函数,可以通过设置pid参数回收指定进程ID的僵尸进程,也可以指定回收任意僵尸进程。
参数说明:
status,和wait()函数相同。
pid,指定要回收进程的进程ID,若设为-1,则默认回收任意一个僵尸进程。
options,设置选项,一般情况下设置成WNOHANG,表示不阻塞。
返回值
若存在僵尸进程,返回被结束僵尸状态进程的进程ID;若不存在僵尸进程返回0;若发生错误,返回-1.
举例:
int main()
{
    pid_t pid;
    int status;
    pid=fork();
    if(pid==0)
    {
        sleep(10);
        exit(10);
    }
    else
    {
        while((pid=waitpid(-1,&status,WNOHANG))==0)
        {
            puts("wating ...");
            sleep(2);
        }
        if(WIFEXITED(status))
        {
            printf("process %d exited,return value = %d\n",pid,WEXITSTATUS(status));
        }
    }
    return 0;
}


缺点:
虽然waitpid()不是阻塞函数,但是使用时需要在循环中使用,只有在回收完僵尸进程后才会执行循环之后的代码。


三 signal函数


函数原型:
sighandler_t signal(int signum, sighandler_t handler);
描述:
系统级别的api,向操作系统注册信号和信号处理函数,当操作系统捕获到注册的信号时会调用该信号处理函数。
参数:
signum,向操作系统注册的信号,子进程结束的信号是SIGCHLD。
handler,信号的处理函数,函数原型一般是void handler(int sig)的形式,函数的参数为操作系统捕获的信号,函数的返回值是void
返回值:
返回之前注册的处理该信号的信号处理函数的函数指针。
举例:
void sig_handling(int sig)
{
    int status;
    pid_t pid;
    if(sig==SIGCHLD)
    {
        pid = waitpid(-1,&status,WNOHANG);
        if(WIFEXITED(status))
        {
            printf("process %d exited,return value=%d\n",pid,WEXITSTATUS(status));
        }
    }
}
 
 
int main()
{
    pid_t pid;
    signal(SIGCHLD,sig_handling);
    pid=fork();
    if(pid==0)
    {
        exit(11);
    }
    else
    {
        sleep(10000);
    }
    return 0;
}


  请注意:
  1、在信号处理函数sig_handling中,也需要用waitpid()来回收僵尸进程,也就是说signal只是一个注册信号的作用,其本身并没有回收僵尸进程的功能。
  2、一旦用signal注册了信号和信号处理函数,一旦发生该信号,会结束进程的sleep()状态,也就是说在父进程的sleep(10000);将会被打断,不会真的睡10000秒。
 
四 sigaction函数


函数原型:
int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);
描述:
signum,和signal一样,表示需要注册的信号。
act,sigaction类型的指针,sigaction类型的定义如下:

struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };
  我们进行使用时,只需填写其sa_handler、sa_mask、sa_flags三个成员,sa_handler为信号处理函数,sa_mask使用sigemptyset()函数进行置空,sa_flags直接赋为0。
  oldact,之前注册的 sigaction 类型的指针。
返回值:
  成功返回0,失败返回-1
举例:
void sig_handling(int sig)
{
    int status;
    pid_t pid;
    if(sig==SIGCHLD)
    {
        pid = waitpid(-1,&status,WNOHANG);
        if(WIFEXITED(status))
        {
            printf("process %d exited,return value=%d\n",pid,WEXITSTATUS(status));
        }
    }
}
 
 
int main()
{
    pid_t pid;
    struct sigaction act;
    act.sa_handler=sig_handling;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;
    sigaction(SIGCHLD,&act,0);
    pid=fork();
    if(pid==0)
    {
        exit(11);
    }
    else
    {
        sleep(10000);
    }
    return 0;
}


  与signal相比,sigaction函数虽然比较繁琐,但是他的长处在于linux系统多版本的兼容性,而部分版本linux是不支持signal函数的,因此在实际的使用中sigaction的使用范围更广。

Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
Git clone [email protected]:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL32
--------------------- 
作者:HymanLiuTS 
来源:CSDN 
原文:https://blog.csdn.net/hyman_c/article/details/53512999 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/ai2000ai/article/details/94384638