1)通过忽略SIGCHLD信号,解决僵尸进程
在server端代码中添加
signal(SIGCHLD, SIG_IGN);
2)通过wait/waitpid方法,解决僵尸进程
signal(SIGCHLD,onSignalCatch); void onSignalCatch(int signalNumber) { wait(NULL); }
Server端部分代码:
//return a socket that have start listened. int mkATCPServer(int serverPort, int backlog = SOMAXCONN) { int sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd == -1) { err_exit("socket error"); } //add address reused int on = 1; if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) == -1) { err_exit("setsockopt SO_REUSEADDR error"); } //band a local address and port struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(serverPort); serverAddr.sin_addr.s_addr = INADDR_ANY; //band an any IP address if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1) { err_exit("bind error"); } //start to listen. if (listen(sockfd,backlog) == -1) { err_exit("listen error"); } return sockfd; } void onSignalCatch(int signalNumber) { waitpid(-1,NULL,WNOHANG); } int main() { //安装SIGCHLD信号处理函数 signal(SIGCHLD,onSignalCatch); int serverSockfd = mkATCPServer(8002); struct sockaddr_in peerAddr; socklen_t peerLen = sizeof(peerAddr); while (true) { //接受链接 int peerSockfd = accept(serverSockfd, (struct sockaddr *)&peerAddr,&peerLen); if (peerSockfd == -1) { err_exit("accept error"); } ..... //其他部分代码与前面相似
问题描述如下:
客户端代码实现代码
//其他代码如前 //.... int main() { int serverSocket[10]; int socketCount = 10; for (int i = 0; i < socketCount; ++i) { serverSocket[i] = mkATCPClient(8002,"127.0.0.1"); } sleep(100); return 0; }
在客户运行过程中按下Ctrl+C,则可以看到在server端启动10个子进程,并且所有的客户端全部一起断开的情况下,产生的僵尸进程数是惊人的(此时也证明了SIGCHLD信号是不可靠的)!
解决方法:
//server端部分代码如下: //其他如前.... void onSignalCatch(int signalNumber) { int ret = 0; //注意此处!!!! while ((ret = waitpid(-1,NULL,WNOHANG) != -1)) ; } int main() { signal(SIGCHLD,onSignalCatch); int serverSockfd = mkATCPServer(8002); ...
从下图可以看出,出了监听server进程,已经没有僵尸进程了!
原文地址:http://blog.csdn.net/zjf280441589/article/details/41748423