一:pid_t waitpid(pid_t pid, int *statloc, int options)
引用UNIX网络编程5.9-5.10节的内容,僵尸进程形成的原因大家都是很清楚了,这里不多解释,我们显然不能留存僵死进程,它们占用内核的空间,最终可能耗尽进程资源,所以我们得正确处理父进程以避免子进程变为僵尸进程。
我们一般使用函数waitpid来等待子进程,pid参数允许我们指定想等待的子进程ID,值为-1表示等待第一个结束的子进程。其次,options参数允许我们指定附加选项,我们一般用的是WNOHANG,它告知waitpid在有尚未终止的子进程在运行时不要阻塞。
二 程序代码
void
sig_chld(int signo)
{
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)//<span style="color: rgb(51, 51, 255); font-family: Arial; font-size: 14px; line-height: 26px;"> /* 使用了WNOHANG参数,waitpid不会在这里等待 */</span>
printf("child %d terminated\n", pid);
return;
}
#include "unp.h"
int
main(int argc, char **argv)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
void sig_chld(int);
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
Signal(SIGCHLD, sig_chld); /* must call waitpid() */
for ( ; ; ) {
clilen = sizeof(cliaddr);
if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
if (errno == EINTR)
continue; /* back to for() */
else
err_sys("accept error");
}
if ( (childpid = Fork()) == 0) { /* child process */
Close(listenfd); /* close listening socket */
str_echo(connfd); /* process the request */
exit(0);
}
Close(connfd); /* parent closes connected socket */
}
}