1.阻塞与非阻塞
非阻塞:程序调用后,不管能不能立刻得到结果,当前进程都会直接返回。如果得到结果则返回成功,否则返回失败。
阻塞:程序调用后,如果不能立刻得到结果,则当前进程会被挂起,无限期等待,直到得到结果时才会返回。
系统调用一般可通过参数控制阻塞或者非阻塞。
常用在IPC通信和网络通信中,需要根据同步或异步设置阻塞和非阻塞:
msgsnd/msgrcv:消息队列发送、接收消息。
semop:信号量操作,用户改变信号量的值。P、V操作。
send/recv,read/write:socket 发送、读写缓冲区。
2.errno ENTIR
errno ENTIR(4) 系统调用被信号中断,一般发生在被阻塞的系统调用中。
在阻塞期间,被阻塞的进程收到了不可屏蔽的信号,操作系统会将信号写入该阻塞进程信号描述符,然后强行将进程状态从 TASK_INTERRUPTABLE 改变至 TASK_RUNNING,调用 schedule() 函数执行,由于进程之前一直被阻塞,而linux是交互型系统,因此,阻塞时间越长,进程动态优先级会被调高,因此该进程能在极短的时间内得到相应。但此时,系统调用需要完成的工作并没完成,提前返回将导致错误,设置 errno 为 EINTR。
3.解决办法
在阻塞调用失败后,检查系统错误码 errno 是否是 ENTIR, 重复当前系统调用。
msgsnd代码示例(msgsnd最后一个参数为0代表当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列):
...
while (1) {
if (msgsnd( msqid, &sendbuf, sendlen, 0) < 0 && errno == ENTIR) {
continue;
}
break;
}
...
参考true0face-系统调用中断。链接:https://blog.csdn.net/true0face/article/details/48132091