OS / Linux / 系统阻塞在系统调用中时如果收到信号,系统如何处理?
今天在看《深入 Linux 内核架构》这本书的时候,看到如题的场景。
之前的处理方式是检测系统调用函数的返回值,如果返回值为 -1 并且 errno 是 EINTR ,那么就知道了该系统调用被中断打断了,需要重新调用该函数。
栗子:
#include
#include
#include
#include
#include volatile int signaled = 0;void handler(int)
{printf("signaled called\n");signaled = 1;
}int main(int argc, char *argv[])
{char ch;struct sigaction sigact;sigact.sa_handler = handler;//sigact.sa_flags = SA_RESTART;sigaction(SIGINT, &sigact, NULL);while (read(STDIN_FILENO, &ch, 1) == -1)printf("signaled call err info = %s\n", strerror(errno));return 0;
}
运行之后不断地执行 Ctrl + C 时,会不断的显示如下内容:
signaled call err info = Interrupted system call
因为在阻塞 read 函数的时候收到了中断信号,导致系统调用函数提前返回。
上述是传统的做法,今天看书中还有另外一种做法,是 linux 参考 BSD 方案,大致流程是当系统阻塞在 read 函数中时,如果系统收到了中断信号,系统调用不会提前返回,内核会在信号处理程序执行结束之后自动重启该调用。
启动上述功能的代码是:
sigact.sa_flags = SA_RESTART;
栗子:
#include
#include
#include
#include
#include volatile int signaled = 0;void handler(int)
{printf("signaled called\n");signaled = 1;
}int main(int argc, char *argv[])
{char ch;struct sigaction sigact;sigact.sa_handler = handler;sigact.sa_flags = SA_RESTART;sigaction(SIGINT, &sigact, NULL);while (read(STDIN_FILENO, &ch, 1) != 1 && !signaled);return 0;
}
运行之后不断地执行 Ctrl + C 时,会不断的显示如下内容:
signaled called
因为程序阻塞在 read 函数,收到中断信号之后,由于内核自动重启了 read 函数,导致程序还是阻塞在 read 函数中,始终无法响应 signaled 的变化,导致程序无法正常退出。
拓展
查看 errno 值含义:
/usr/include/asm-generic/errno-base.h 或者 errno.h
(SAW:Game Over!)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
