36-多进程并发服务器(僵尸进程与信号处理)
2017-04-21 09:59
316 查看
在上一篇文章中,最后遗留了一个僵尸进程的问题。一旦客户端关闭连接,服务器子进程就会退出,然而父进程仍然存在,就产生了“白发人送黑发人”的场景。如果父进程没有主动回收(wait)子进程,或者没有忽略 SIGCHLD 信号,退出的子进程就会成为僵尸进程。
代码托管在 gitos 上,请使用下面的命令获取:
代码托管在 gitos 上,请使用下面的命令获取:
git clone https://git.oschina.net/ivan_allen/unp.git[/code]
如果你已经 clone 过这个代码了,请使用 Git pull 更新一下。本文所使用的程序路径是:unp/program/echo/processzombie1. 处理僵尸进程
1.1 方案一:忽略 SIGCHLD 信号
这是最简单的方案,直接忽略掉 SIGCHLD 就不会产生僵尸进程了。只要在程序初始化阶段调用:signal(SIGCHLD, SIG_IGN);1.2 方案二:捕捉 SIGCHLD 并 wait
实际上,在我们学习 Linux 环境编程的时候,就已经学习过处理办法了,只要让父进程 wait 子进程就行了。不过,比较推荐的方案是使用捕捉 SIGCHLD 信号,然后在信号处理函数里异步 wait 子进程。// 信号处理函数 void handler(ing sig) { pid_t pid; int stat; if (sig == SIGCHLD) { // 想一想,为什么要循环? while(1) { // WNOHANG 表示不阻塞 pid = waitpid(-1, &stat, WNOHANG); // 返回 -1 表示没有子进程了,返回 0 表示有子进程,但是子进程没有退出。 if (pid <= 0) break; printf("child %d terminated\n", pid); } } }2. 信号打断低速系统调用
这个是一个坑,之前我们也有讲过,请参考《中断系统调用与自动重启动》,这里我简单总结一下:
进程捕捉到信号后,会打断某些正在阻塞中的函数(低速系统调用,比如 read,accept,connect 等),这种函数如果被信号打断,会直接返回错误,同时设置 errno = EINTR.
实际上,这并不是错误,如果我们没有处理这种情况,让程序直接退出,会让一个运行的很好的服务器停止。所以为了让服务器或客户端更加健壮,我们需要额外的处理这种错误,比如:// accept 返回错误,可能是被信号打断。如果被打断,不认为它是错误。 ret = accept(listenfd, ...); if (ret < 0) { if (errno == EINTR) contine; else exit(1); }3. 实验
在 sun 主机上启动服务器$ ./echo -s -h sun
在 flower 主机上启动客户端$ ./echo -h sun
随便输入一些数据后,按下 CTRL D 让客户端主动退出。
运行结果
图1 服务器运行结果
从图 1 中我们可以看到,子进程退出时,给父进程发送了 SIGCHLD 信号,信号处理函数执行完后,发现 accept 直接返回一个错误,屏幕打印“Interrupted system call(被中断的系统调用)”。但这并不是一个错误,我们需要让服务器继续运行。
图2 客户端按下 CTRL D 退出4. 总结
掌握处理僵尸进程的办法
知道低速系统调用会被信号打断,同时 errno = EINTR.
思考:为什么在信号处理函数中处理子进程时,需要循环操作?(提示:参考《标准信号及其不可靠性》)
相关文章推荐
- 用select单个进程处理并发服务器
- Linux下信号SIGCHLD处理不当产生僵尸进程的问题
- python练习笔记——利用信号signal处理僵尸进程
- linux下的僵尸进程处理SIGCHLD信号
- [转] linux下的僵尸进程处理SIGCHLD信号
- linux下的僵尸进程处理SIGCHLD信号【转】
- Linux并发回射服务器(二):处理僵死进程
- 每天一小步——自写服务器与信号处理僵尸子进程
- 回射客户端服务器中僵尸进程的处理( the solution of zombie process in the echo client && server )
- 用TCP/TP进行网际互连(6) ———— 利用I/O复用完成单进程并发服务器的处理
- linux下的僵尸进程处理SIGCHLD信号
- 并发处理时防止产生僵尸进程
- 多进程并发如何防止僵尸进程——服务器开发
- 说说Linux中的信号处理和僵尸进程的避免
- linux下的僵尸进程处理SIGCHLD信号
- Linux 网络编程详解七(并发僵尸进程处理)
- 这个模型用来测试并发服务器,是否会产生僵尸进程
- 说说Linux中的信号处理和僵尸进程的避免
- linux下的僵尸进程处理SIGCHLD信号
- 服务器并发处理能力