非阻塞(nonblock)socket接口会否出现EINTR错误

阅读更多
对于socket接口(指connect/send/recv/accept..等等后面不重复,不包括不能设置非阻塞的如select),在阻塞模式下有可能因为发生信号,返回EINTR错误,由用户做重试或终止。

但是,在非阻塞模式下,是否出现这种错误呢?
对此,重温了系统调用、信号、socket相关知识,得出结论是: 不会出现

首先,
1.信号的处理是在用户态下进行的,也就是必须等待一个系统调用执行完了才会执行进程的信号函数,所以就有了信号队列保存未执行的信号
2.用户态下被信号中断时,内核会记录中断地址,信号处理完后,如果进程没有退出则重回这个地址继续执行

socket接口是一个系统调用,也就是即使发生了信号也不会中断,必须等socket接口返回了,进程才能处理信号。
也就是,EINTR错误是socket接口主动抛出来的,不是内核抛的。socket接口也可以选择不返回,自己内部重试之类的..

那阻塞的时候socket接口是怎么处理发生信号的?

举例
socket接口,例如recv接口会做2件事情,
1.检查buffer是否有数据,有则复制清除返回
2.没有数据,则进入睡眠模式,当超时、数据到达、发生错误则唤醒进程处理

socket接口的实现都差不了太多,抽象说
1.资源是否立即可用,有则返回
2.没有,就等...

对于
1.这个时候不管有没信号,也不返回EINTR,只管执行自己的就可以了
2.采用睡眠来等待,发生信号的时候进程会被唤醒,socket接口唤醒后检查有无未处理的信号(signal_pending)会返回EINTR错误。

所以
socket接口并不是被信号中断,只是调用了睡眠,发生信号睡眠会被唤醒通知进程,然后socket接口选择主动退出,这样做可以避免一直阻塞在那里,有退出的机会。非阻塞时不会调用睡眠。

我们看看linux内核里的实现
linux kernel 3.5.5
非阻塞(nonblock)socket接口会否出现EINTR错误_第1张图片

非阻塞(nonblock)socket接口会否出现EINTR错误_第2张图片

非阻塞(nonblock)socket接口会否出现EINTR错误_第3张图片

参考资料:
《UNIX环境高级编程》
《UNIX网络编程》
《TCP/IP详解 卷2:实现》
《深入Linux内核架构》
  • 非阻塞(nonblock)socket接口会否出现EINTR错误_第4张图片
  • 大小: 30.6 KB
  • 非阻塞(nonblock)socket接口会否出现EINTR错误_第5张图片
  • 大小: 51.5 KB
  • 非阻塞(nonblock)socket接口会否出现EINTR错误_第6张图片
  • 大小: 25.4 KB
  • 查看图片附件

你可能感兴趣的:(nonblock,socket,linux/unix,signal,sleep)