Linux中的SIGCHLD及wait,waitpid的使用

来源:互联网 发布:产业经济学研究生知乎 编辑:程序博客网 时间:2024/06/05 04:55

    在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程。按系统默认将忽略此信号。如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。信号的捕捉函数中通常调用wait(waitpid)函数以取得进程ID和其终止状态

    该信号常用于处理僵死(zombie)进程,通过在listen调用后增加如下函数调用:

signal(SIGCHLD, sig_chld);   //void sig_chld(int signo){    pid_t pid;    int stat;    pid = wait(&stat);    //    printf("child %d terminated\n",pid);       return;}
    调用wait后,进程立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait 就会收集这个子进程的信息, 并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

   不过wait有其局限性,在多客户端连接下,服务器会派生多个进程,在多客户端同时终止情况下,这会导致同一时刻有多个SIGCHLD信号递交给父进程,而此时的wait却只能处理一个进程(不同主机上运行一般执行2次 <见unp 5.10>),这是就需要waitpid登场了。

void sig_chld(int signo){    pid_t pid;    int stat;    while((pid=waitpid(-1, &stat, WHOHANG)) > 0)        printf("child %d terminated\n", pid);    return;}
    如上程序,我们在一个循环内调用waitpid,以获取所以终止子进程状态。我们必须指定WNOHANG选项,他告知waitpid在尚未终止的子进程在运行时不要阻塞。我们不能在循环内调用wait,因为没有办法阻止wait在正运行的子进程中还有未终止的进程时阻塞。

如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD, SIG_IGN) 通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收, 并不再给父进程发送信号(我在调度器中使用了这种)

wait:
相关函数 waitpid,fork
表头文件
#include<sys/types.h>
#include<sys/wait.h>
定义函数 pid_t wait (int * status);
函数说明
wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考waitpid()。
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。

waitpid:    

定义函数 pid_t waitpid(pid_t pid,int * status,int options);
函数说明
waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。

参数pid 为欲等待的子进程识别码,其他数值意义如下:
pid<-1 等待进程组识别码为pid 绝对值的任何子进程。
pid=-1 等待任何子进程,相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid 的子进程。

参数option可以为0或下面的OR组合:
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。

子进程的结束状态返回后存于status,下面有几个宏可判别结束情况
WIFEXITED(status)如果子进程正常结束则为非0 值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。

返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。






0 0
原创粉丝点击