Posted on 2009-03-27 15:47
Prayer 阅读(987)
评论(0) 编辑 收藏 引用 所属分类:
LINUX/UNIX/AIX
当进程正在执行一个系统调用时,如果被信号中断,这时会发生什么呢?
当一个低速调用阻塞期间捕捉到一个信号, 则该系统调用就被中断不再继续执行。 该系统调用返回出错,起errono设置为EINTR。 因为发生信号, 进程捕捉到它, 这将是一个很好的机会来唤醒阻塞的系统调用。
但有一个问题就是如果该系统调为read(), 正在等待终端输入, 如果被信号中断的话, 难免会影响整个程序的正确性, 所以有些系统使这类系统调用自动重启动。就是一旦被某信号中断, 立即再启动。
如下面的signal1函数实现:
#include <signal.h>
#include "ourhdr.h"
typedef void Sigfunc(int);
Sigfunc *
signal1(int signo, Sigfunc *func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo ==SIGALRM)
{
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
}
else
{
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /*这里对所有的信号都设置了自动再启动,唯独没有SIGALRM*/
#endif
}
if (sigaction(signo, &act, &oact)<0)
return(SIG_ERR);
return (oact.sa_handler);
}
为什么偏偏面对SIGALRM信号, 系统调用不设置自动重启动呢? 这时为了我们方便给read等低速系统调用定时。 我们不希望它一遇到某个信号变自动重启动,也不希望它无限制的阻塞下去。 于是用alarm()进行定时, 一旦超出某个时间, 便被ALRM信号中断唤醒,且不再重启动。
下面这段程序用来测试上面的signal1函数, 对一个read系统调用, 如何给它定时的:
#include <signal.h>
#include "ourhdr.h"
#include "10-12.c"
#define MAXLINE 1024
static void sig_alrm(int);
int
main(void)
{
int n;
char line[MAXLINE];
if (signal1(SIGALRM, sig_alrm) == SIG_ERR)
perror("signal");
alarm(10);
if ( (n = read(STDIN_FILENO, line, MAXLINE)) < 0)
perror("read");
alarm(0);
write(STDOUT_FILENO, line, n);
write(STDOUT_FILENO, "exit\n", 5);
exit(0);
}
static void
sig_alrm(int signo)
{
write(STDOUT_FILENO, "recieved signal -ALRM\n", 22);
return;
}
在我的系统中, 如果调用默认的signal函数, 该read()系统调用将会自动重启动, 所谓的alarm定时也就不起作用了。