系统调用可分为两类:慢速系统调用和其他系统调用
- 慢速系统调用:可能会使进程永远阻塞的一类,如果在阻塞期间收到一个信号,该系统调用就被中断,不再继续执行(早期);也可以设定系统调用是否重启。如: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;
}
输出结果: