zoukankan      html  css  js  c++  java
  • 信号之sigaction函数

    sigaction函数的功能是检查或修改与指定信号相关联的处理动作(或同时执行这两种操作)。

    #include <signal.h>
    int sigaction( int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
    返回值:若成功则返回0,若出错则返回-1

    其中,参数signo是要检测或修改其具体动作的信号编号。若act指针非空,则要修改其动作。如果oact指针非空,则系统经由oact指针返回该信号的上一个动作。此函数使用下列结构:

    struct sigaction {
        void    (*sa_handler)(int);    /* addr of signal handler, or SIG_IGN, or SIG_DFL */
        sigset_t    sa_mask;           /* additional signals to block */
        int    sa_flags;               /* signal options */
    
        /* alternate handler */
        void    (*sa_sigaction)(int, siginfo_t *, void *);
    };

    当更改信号动作时,如果sa_handler字段包含一个信号捕捉函数的地址(与常量SIG_IGN或SIG_DFL相对),则sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加到进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。这样,在调用信号处理程序时就能阻塞某些信号。在信号处理程序被调用时,操作系统建立的新信号屏蔽字包括正被递送的信号。因此保证了在处理一个给定的信号时,如果这种信号再次发生,那么它会被阻塞到对前一个信号的处理结束为止。

    一旦对给定的信号设置了一个动作,那么在调用sigaction显式地改变它之前,该设置就一直有效。(早期版本并非如此,而是:在进程每次接到信号对其进行处理时,随即将该信号动作复位为默认值。见http://www.cnblogs.com/nufangrensheng/p/3515035.html

    act结构的sa_flags字段指定对信号进行处理的各个选项。

                                                            表10-5 处理每个信号的选项标志(sa_flags)

    2012082515302617

    sa_sigaction字段是一个替代的信号处理程序,当在sigaction结构中使用了SA_SIGINFO标志时,使用该信号处理程序。对于sa_sigaction字段和sa_handler字段这两者,其实现可能使用同一存储区,所以应用程序只能一次使用这两个字段中的一个。

    通常,按下列方式调用信号处理程序:

    void handler(int signo);

    但是,如果设置了SA_SIGINFO标志,那么按下列方式调用信号处理程序:

    void handler(int signo, siginfo_t *info, void *context);

    siginfo_t结构包含了信号产生原因的有关信息。该结构的大致样式如下所示:

    struct siginfo {
        int      si_signo;        /* signal number */
        int      si_errno;        /* if nonzero, errno value from <errno.h> */
        int      si_code;         /* additional info (depends on signal) */
        pid_t    si_pid;          /* sending process ID */
        uid_t    si_uid;          /* sending process real user ID */
        void    *si_addr;         /* address that caused the fault */
        int      si_status;       /* exit value or signal number */
        long     si_band;         /* band number for SIGPOLL */
        /* possibly other fields also */
    };

    各种信号的si_code值(包括上面的相关数据结构和标志选项),可通过man sigaction命令进行查看。

    若信号是SIGCHLD,则将设置si_pid、si_status和si_uid字段。

    若信号是SIGILL或SIGSEGV,则si_addr包含造成故障的根源地址,尽管该地址可能并不准确。

    若信号是SIGPOLL,那么si_band字段将包含STREAMS消息的优先级(priority band),该消息产生POLL_IN、POLL_OUT或POLL_MSG事件。

    si_errno字段包含错误编号,它对应于引发信号产生的条件,并由实现定义。

    信号处理程序的context参数是无类型指针,它可被强制转换为ucntext_t结构类型,用于标识信号传递时进程的上下文。

     实例:signal函数

    现在用sigaction实现signal函数。很多平台都是这样做的。

    程序清单10-12 用sigaction实现signal函数

    #include "apue.h"
    
    /* Reliable version of signal(), using POSIX sigaction(). */
    Sigfunc *
    signal(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;
    #endif
        }
        if(sigaction(signo, &act, &oact) < 0)
            return(SIG_ERR);
        return(oact.sa_handler);
    }

    注意,必须用sigemptyset函数初始化act结构的sa_mask成员。不能保证:act.sa_mask = 0;会做同样的事情。

    对除SIGALRM以外的所有信号,我们都有尝试设置SA_RESTART标志,于是被这些信号中断的系统调用都能自动重启动。不希望重启动由SIGALRM信号中断的系统调用的原因是:我们希望对I/O操作可以设置时间限制。

    实例:signal_intr函数

    程序清单10-13是signal函数的另一种版本,它力图阻止任何被中断的系统调用重启动。

    程序清单10-13 signal_intr函数

    #include "apue.h"
    
    Sigfunc *
    signal_intr(int signo, Sigfunc *func)
    {
        struct sigaction     act, oact;
    
        act.sa_handler = func;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
    #ifdef    SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT;
    #endif
        if(sigaction(signo, &act, &oact) < 0)
            return(SIG_ERR);
        return(oact.sa_handler);
    }

    如果系统定义了SA_INTERRUPT标志,那么为了提高可移植性,我们在sa_flags中增加该标志,这样也就阻止了被中断的系统调用重启动。

    本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

  • 相关阅读:
    ZOJ2587 Unique Attack(判定最小割唯一性)
    SPOJ371 Boxes(最小费用最大流)
    SGU185 Two shortest(最小费用最大流/最大流)
    POJ2112 Optimal Milking(最大流)
    HDU3996 Gold Mine(最大权闭合子图)
    POJ3680 Intervals(最小费用最大流)
    SPOJ 7258 Lexicographical Substring Search(后缀自动机)
    HDU 4436 str2int(后缀自动机)
    SPOJ 1812 Longest Common Substring II(后缀自动机)
    CodeForces 235C Cyclical Quest(后缀自动机)
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3515945.html
Copyright © 2011-2022 走看看