非阻塞(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 
 

 

 

参考资料: 
《UNIX环境高级编程》 
《UNIX网络编程》 
《TCP/IP详解 卷2:实现》 
《深入Linux内核架构》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值