unp TCP 客户端服务器回射程序中对SIGCHLD信号的处理
2016-01-30 15:01
423 查看
第五章中,有一个例子模拟客户端并发的终止TCP连接,服务器捕捉并处理SIGCHLD信号并调用waitpid函数防止僵死进程的出现。信号处理函数中核心的一句是:
这是在使用wait函数时不能解决N个子进程同时终止时导致只有1个子进程被wait而其他N-1个子进程变成僵死进程的问题而采用的改进方法,使用wait的信号处理函数
[b]什么是僵死进程?[/b]
僵死进程就是,进程本身退出了,而它的父进程未退出,并且父进程没有对它进行wait类处理,导致进程占有的资源,例如进程pid,记录进程信息的结构没有被释放,进程进入僵死态,这样的进程就叫僵死进程。
[b]僵死进程的危害[/b]
一旦僵死进程累积,比如有一个长期运行的程序不断的产生僵死进程,那么最终会耗尽系统可用的pid和内存,这样就无法创建新的进程了。就算未耗尽这些,过多的僵死进程对内存的消耗也会影响机器的性能。
[b]如何防止僵死进程的出现?[/b]
父进程在调用wait类函数时,就可以释放子进程的资源,子进程就不会变成僵死进程。通常都是通过捕捉SIGCHLD信号,在信号处理函数里面调用wait类函数。
先man下wait和waitpid
wait:
函数阻塞,直到任意一个子进程终止,或者被一个信号中断。终止的这个子进程的退出状态返回存储在参数 status的低位字节,返回值为结束的子进程pid。
waitpid:
根据pid和options做出不同的响应。
pid > 0,wait进程id为pid的子进程
pid = 0,wait进程组id为调用进程ID的任意一个子进程
pid = -1,wait任意一个子进程
pid < -1, wait 进程组id为|pid|的任意一个子进程
而options又提供不同的选项,它可以为0或者一个或多个选项的or组合
WNOHANG
当未发现有任何子进程退出时立即返回。
WUNTRACED
WCONTINUED
由于linux信号机制是不进行排队的,所以对于同时发出的多个信号,信号处理程序最多捕捉2次,而wait函数每次最多处理一个子进程,所以,当同时结束的子进程超过2个后,必然会出现僵死进程。那么为什么 while ( (pid = waitpid(-1, &statloc, WNOHANG)) > 0 ) 可以解决这个问题呢?
假设有5个子进程,p1,p2....p5,首先p1,p2结束,捕获到信号,上面的while+waitpid语句将一次性把所有已结束的子进程处理完毕,此时仍有3个子进程未结束,那么waitpid返回0,退出循环,如果在处理函数调用期间,又有一个p3结束,等到处理函数返回时,马上又捕捉到了信号,再次进入处理函数对p3进行处理,这样一来不管子进程是在处理函数处理期间结束还是之前之后结束,信号都能被捕捉,不管结束的是1个子进程还是多个子进程,每个都能被waitpid处理,这样就不再会有僵死进程出现了。
为什么是用 while ( (pid = waitpid(-1, &statloc, WNOHANG)) > 0 ) ,而不是 '>= 0'??等于0是指仍然存在运行的子进程,但是子进程未结束,如果使用>=0,那么只要有一个子进程未结束,处理函数将在while中循环,这样父进程将不能被执行,所以不采用 >=。
一直对于采用while+waitpid为什么能防止僵死进程出现存在不解,其根本原因在于我认为一旦信号丢失,那么与之对于的那个子进程也将不会被waitpid处理。其实信号在这里只是起一个通知作用,比如,我可以在父进程里面采用轮询waitpid,不用信号处理函数也能wait所有结束的子进程。我一个小时前结束了一个子进程,一个小时后才用waitpid来处理,照样可以让这个处于僵死态的子进程得到正确的处理。
关于以上问题的讨论http://bbs.chinaunix.net/thread-828942-1-1.html这个帖子做了比较好的解释。
while ( (pid = waitpid(-1, &statloc, WNOHANG)) > 0 ) { printf("wait child pid:%ld\n",(long)pid); }
这是在使用wait函数时不能解决N个子进程同时终止时导致只有1个子进程被wait而其他N-1个子进程变成僵死进程的问题而采用的改进方法,使用wait的信号处理函数
pid = wait(&statloc);
[b]什么是僵死进程?[/b]
僵死进程就是,进程本身退出了,而它的父进程未退出,并且父进程没有对它进行wait类处理,导致进程占有的资源,例如进程pid,记录进程信息的结构没有被释放,进程进入僵死态,这样的进程就叫僵死进程。
[b]僵死进程的危害[/b]
一旦僵死进程累积,比如有一个长期运行的程序不断的产生僵死进程,那么最终会耗尽系统可用的pid和内存,这样就无法创建新的进程了。就算未耗尽这些,过多的僵死进程对内存的消耗也会影响机器的性能。
[b]如何防止僵死进程的出现?[/b]
父进程在调用wait类函数时,就可以释放子进程的资源,子进程就不会变成僵死进程。通常都是通过捕捉SIGCHLD信号,在信号处理函数里面调用wait类函数。
先man下wait和waitpid
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options);
wait:
函数阻塞,直到任意一个子进程终止,或者被一个信号中断。终止的这个子进程的退出状态返回存储在参数 status的低位字节,返回值为结束的子进程pid。
waitpid:
根据pid和options做出不同的响应。
pid > 0,wait进程id为pid的子进程
pid = 0,wait进程组id为调用进程ID的任意一个子进程
pid = -1,wait任意一个子进程
pid < -1, wait 进程组id为|pid|的任意一个子进程
而options又提供不同的选项,它可以为0或者一个或多个选项的or组合
WNOHANG
当未发现有任何子进程退出时立即返回。
WUNTRACED
WCONTINUED
由于linux信号机制是不进行排队的,所以对于同时发出的多个信号,信号处理程序最多捕捉2次,而wait函数每次最多处理一个子进程,所以,当同时结束的子进程超过2个后,必然会出现僵死进程。那么为什么 while ( (pid = waitpid(-1, &statloc, WNOHANG)) > 0 ) 可以解决这个问题呢?
假设有5个子进程,p1,p2....p5,首先p1,p2结束,捕获到信号,上面的while+waitpid语句将一次性把所有已结束的子进程处理完毕,此时仍有3个子进程未结束,那么waitpid返回0,退出循环,如果在处理函数调用期间,又有一个p3结束,等到处理函数返回时,马上又捕捉到了信号,再次进入处理函数对p3进行处理,这样一来不管子进程是在处理函数处理期间结束还是之前之后结束,信号都能被捕捉,不管结束的是1个子进程还是多个子进程,每个都能被waitpid处理,这样就不再会有僵死进程出现了。
为什么是用 while ( (pid = waitpid(-1, &statloc, WNOHANG)) > 0 ) ,而不是 '>= 0'??等于0是指仍然存在运行的子进程,但是子进程未结束,如果使用>=0,那么只要有一个子进程未结束,处理函数将在while中循环,这样父进程将不能被执行,所以不采用 >=。
一直对于采用while+waitpid为什么能防止僵死进程出现存在不解,其根本原因在于我认为一旦信号丢失,那么与之对于的那个子进程也将不会被waitpid处理。其实信号在这里只是起一个通知作用,比如,我可以在父进程里面采用轮询waitpid,不用信号处理函数也能wait所有结束的子进程。我一个小时前结束了一个子进程,一个小时后才用waitpid来处理,照样可以让这个处于僵死态的子进程得到正确的处理。
关于以上问题的讨论http://bbs.chinaunix.net/thread-828942-1-1.html这个帖子做了比较好的解释。
相关文章推荐
- OkHttp,Retrofit 1.x - 2.x 基本使用
- TCP、UDP、IP 协议分析
- Servlet服务器 HTTP 响应
- 神经网络 --学习之路,资料汇编
- 抓包分析TCP的三次握手和四次握手
- ios http请求
- QT加载网络图片
- 嵌入式Linux之相关网络环境的搭建
- JAVA网络爬虫WebCollector深度解析——爬虫内核
- 如何对Android设备进行网络抓包
- VMware 网络连接的几种方式
- Android-AndroidFlux-异步请求和网络
- XenServer部署系列——网络配置
- android-async-http cancelRequests
- 使用命令行查看网络连接情况
- http://my.oschina.net/chihz/blog/56256
- Unity3d 网络编程(二)(Unity3d内建网络各项參数介绍)
- 使用clumsy模拟网络延迟
- Java——网络编程
- Network 【HTTP通信过程/请求】