Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
  当进程正在执行一个系统调用时,如果被信号中断,这时会发生什么呢?

     当一个低速调用阻塞期间捕捉到一个信号, 则该系统调用就被中断不再继续执行。 该系统调用返回出错,起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定时也就不起作用了。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理