网络编程中wait与waitpid的区别

问题:   

    一个unp中第五章的例子:有5个客户端几乎同时向服务器发送终止连接,这时在服务器端将几乎同时产生SIGCHILD信号,然而信号在内核中是不排队的,信号处理函数只执行一次(我的理解是5个信号几乎同时到达,当第一个信号被处理时,其他4个信号是未决的,当信号处理函数处理完第一个到达的信号后,由于没有产生信号,信号处理函数将不会被再次调用)。那么在目前情况下,父进程怎样才能捕获到所有的子进程的退出状态呢?

 

分析:

    在SIGCHLD的handler中添加如下代码显然不行:

void
sig_chld(int signo)
{
     pid_t   pid;
     int     stat;

     pid = wait(&stat);
     printf("child %d terminated/n", pid);
     return;
}

    因为使用wait时,它只等到第一个SIGCHLD到达的子进程,之后就如上所示return了。在信号处理函数只能执行一次的前提下,其他4个SIGCHLD信号就没有被处理。

    而如果在handler中使用如下的方式就可以:

void
sig_chld(int signo)
{
    pid_t   pid;
    int     stat;

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

    原因分析如下:在while循环中使用waitpid的非阻塞模式(WNOHANG),当第一个信号到达时,printf然后回到while继续waitpid,接着第二个信号到达,依次处理,直到这5个信号都被处理完之后,根据WNOHANG常量的说明“The waitpid function will not block if a child specified by pid is not immediately available. In this case, the return value is 0. ”(见APUE2中8.6节),所以waitpid将返回0,跳出while循环,这样子进程的终止状态都被捕获到了,父进程继续做它的事。

 

总结:

    wait与waitpid的主要区别:

    (1)waitpid能够等指定pid的子进程;而wait只能等第一个到达的子进程。

    (2)waitpid通过指定WNOHANG可以不阻塞,没有可用的子进程就立即返回0;而wait要求父进程一直阻塞。

    上面这两点其实就是waitpid比wait多了1、3两个参数。

 

补充:

    查看源码,wait就是包装过的waitpid,include/unistd.h

static inline pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}

你可能感兴趣的:(网络编程中wait与waitpid的区别)