Slow system call
该术语适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用是指调用永远无法返回,多数网络支持函数都属于这一类。如:若没有客户连接到服务器上,那么服务器的accept调用就会一直阻塞。
慢系统调用可以被永久阻塞,包括以下几个类别:
(1)读写‘慢’设备(包括pipe,终端设备,网络连接等)。读时,数据不存在,需要等待;写时,缓冲区满或其他原因,需要等待。读写磁盘文件一般不会阻塞。
(2)当打开某些特殊文件时,需要等待某些条件,才能打开。例如:打开中断设备时,需要等到连接设备的modem响应才能完成。
(3)pause和wait函数。pause函数使调用进程睡眠,直到捕获到一个信号。wait等待子进程终止。
(4)某些ioctl操作。
(5)某些IPC操作。
EINTR错误产生的原因
早期的Unix系统,如果进程在一个慢系统调用(slow system call)中阻塞时,当捕获到某个信号且相应信号处理函数返回时,这个系统调用被中断,调用返回错误,设置errno为EINTR(相应的错误描述为“Interrupted system call”)。
怎么看哪些系统条用会产生EINTR错误呢?用man啊!
如何处理被中断的系统调用
既然系统调用会被中断,那么别忘了要处理被中断的系统调用。有三种处理方式:
◆ 人为重启被中断的系统调用
◆ 安装信号时设置 SA_RESTART属性(该方法对有的系统调用无效)
◆ 忽略信号(让系统不产生信号中断)
慢系统调用(slow system call)会被信号中断,系统调用函数返回失败,并且errno被置为EINTR(错误描述为“Interrupted system call”)。
处理方法有以下三种:①人为重启被中断的系统调用;②安装信号时设置 SA_RESTART属性;③忽略信号(让系统不产生信号中断)。
有时我们需要捕获信号,但又考虑到第②种方法的局限性(设置 SA_RESTART属性对有的系统无效,如msgrcv),所以在编写代码时,一定要“人为重启被中断的系统调用”。