1. 背景
在阻塞系统调用中,我们经常会遇到一种系统调用返回过慢或永远阻塞的情况。此时我们需要让系统调用能够快速返回,提高系统整体性能。我们可以利用中断机制,使得系统调用被中断而成功返回。
2. 原理
- 利用alarm函数为进程注册一个闹钟,当闹钟被系统唤醒时将,系统会将SIGALRM信号回馈给进程。
- SIGALRM信号的默认操作是终止进程。为了让进程不终止,需要利用sigaction函数向系统注册信号处理函数(此处为啥不用signal注册信号处理函数)。
3. sigaction & signal异同点
- 相同点
- 均能向系统注册信号处理函数
- 异同点
- signal注册信号处理函数,系统调用会自动重启而不会返回
- sigaction
- 默认情况下系统调用不会自动重启,函数将返回错误码并值errno为EINTR
- 只有中断信号的SA_RESTART标志有效时,系统调用才会自动重启
4. 实例
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
static void null_sig_handler(int sig)
{
}
#if 1
static struct sigaction sig_handler = {
.sa_handler = null_sig_handler,
};
#endif
int main(int argc, const char *argv[])
{
char buffer[128] = {0};
#if 1
sigaction(SIGALRM, &sig_handler, NULL);
#else
signal(SIGALRM, null_sig_handler);
#endif
for (; ; ) {
alarm(2);
int len = read(STDIN_FILENO, buffer, sizeof(buffer));
printf("len[%d], %s\n", len, strerror(errno));
}
return 0;
}
5. 输出结果
len[-1], Interrupted system call
len[-1], Interrupted system call
len[-1], Interrupted system call
len[-1], Interrupted system call
len[-1], Interrupted system call
len[-1], Interrupted system call
len[-1], Interrupted system call