转自 http://blog.csdn.net/keshacookie/article/details/40717059?utm_source=tuicool服务器
咱们用慢系统调用来描述那些可 能永远堵塞的系统调用(函数调用),如:accept,read等。永远堵塞的系统调用是指调用有可能永远没法返回,多数网络支持函数都属于这一类。例 如,若是没有客户链接到服务器上,则服务器对accept的调用就没有返回保证。相似的,若是客户从未发送过一行要求服务器回射的文本,则服务器对 read的调用将永不返回。其余慢系统调用的例子是对管道和终端设备的读写。有一个例外,就是磁盘IO,他通常都返回调用者。
当一个进程堵塞与慢系统调用时捕获到一个信号,等到信号处理程序返回时,系统调用可能返回一个EINTR错误。有些内核自动重启某些被中断的系统调用。为 了便于移植,当咱们编写一个捕获信号的程序时(多数并发服务器捕获SIGCHLD),咱们必须对慢系统调用返回EINTR有所准备。
cookie
为了处理一个被中断的accept,咱们对accept的调用尽心了处理,其余慢系统调用函数也能够照此思路进行处理:网络
第一种方法: 用continue进入for的下一次循环,从而重启被中断的系统调用;并发
或者 用goto来实现同样的功能,也一样让被中断的系统调用重启;函数
另外要说明的是:ui
适用于慢系统调用的基本规则是:当阻塞于某个慢系统调用的一个进程捕获某个信号切相应信号处理函数返回时,该系统调用可能返回一个EINTR错误;而有些系统内核会自动重启某些被中断的系统调用; 这点要注意;spa
在这段代码中,咱们所作 的就是本身重启被中断的系统调用,这对于accept以及其余诸如read,write,select和open这样的函数是合适的,但有一个函数咱们不 能本身重启:connect。若是这个函数返回INTER,咱们就不能再调用他,不然返回错误。当connet被一个捕获的信号中断并且不自动重启时,我 们必须调用select来等待链接完成。.net
最后,当咱们编写处理accept返回EINTR错误的TCP服务器最终版本的时候,首先要注意幾個問題:blog
>>> 当fork子进程时,必须捕获SIGCHLD信号(SIGCHLD信号是子进程结束时,向内核发送的信号)进程
>>> 当捕获信号时,必须处理被中断的系统调用
>>> SIGCHLD的信号处理函数(sig_chld)必须正确编写,应使用waitpid函数杀死僵死进程;
如下就是 “处理accept函数返回EINTR错误的TCP服务器程序最终版本”: