系统调用可分为两类:慢速系统调用和其他系统调用
- 慢速系统调用:可能会使进程永远阻塞的一类,如果在阻塞期间收到一个信号,该系统调用就被中断,不再继续执行(早期);也可以设定系统调用是否重启。如:read、write、pause、wait等等
- 其他系统调用:getpid、getppid、fork...
结合pause,回顾慢速系统调用:
- 想中断pause,信号不能被屏蔽
- 信号的处理方式必须是捕捉(默认、忽略都不可以)
- 中断后返回-1,设置errno为EINTR(表“被信号中断”)
可修改sa_flags参数来设置被信号中断系统调用是否重启。SA_INTERRURT 不重启。SA_RESTART重启。
扩展了解:
sa_flags还有许多可选参数,适用不同情况,如:捕捉到信号后,在执行捕捉函数期间,不希望屏蔽该信号,可将sa_flags设置为SA_NODEFER,除非sa_mask中包含该信号。
1. 测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>void int_handler(int signum)
{printf("int handler %d\n", signum);
}int main(int argc, char **argv)
{char buf[100];ssize_t ret;struct sigaction oldact;struct sigaction act;act.sa_handler = int_handler;act.sa_flags = 0;act.sa_flags |= SA_RESTART;sigemptyset(&act.sa_mask);if (-1 == sigaction(SIGINT, &act, &oldact)) {printf("sigaction failed!\n");return -1;}bzero(buf, 100);ret = read(STDIN_FILENO, buf, 10);if (ret == -1) {printf("read error %s\n", strerror(errno));}printf("read %d bytes, content is %s\n", (int)ret, buf);sleep(10);return 0;
}
输出结果:
2. 测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>void int_handler(int signum)
{printf("int handler %d\n", signum);
}int main(int argc, char **argv)
{char buf[100];ssize_t ret;struct sigaction oldact;struct sigaction act;act.sa_handler = int_handler;act.sa_flags = 0;// act.sa_flags |= SA_RESTART;sigemptyset(&act.sa_mask);if (-1 == sigaction(SIGINT, &act, &oldact)) {printf("sigaction failed!\n");return -1;}bzero(buf, 100);ret = read(STDIN_FILENO, buf, 10);if (ret == -1) {printf("read error %s\n", strerror(errno));}printf("read %d bytes, content is %s\n", (int)ret, buf);sleep(10);return 0;
}
输出结果:
参考资料
1. linux SA_RESTART的问题
2. 44-中断系统调用与自动重启动