ijava学习网> 知识分享> Web 服务> sigaction函数的详解

sigaction函数的详解

时间: 2018-11-09 09:33:08 标签


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

#includeint 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显式地改变它之前,该设置就一直有效。

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

struct siginfo {
    int      si_signo;        /* signal number */
    int      si_errno;        /* if nonzero, errno value from*/
    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中增加该标志,这样也就阻止了被中断的系统调用重启动。

 


版权说明| 关于ijava| 合作伙伴| 联系我们| 网站地图| 招贤纳士

Copyright © 2017 www.ijava.com All Rights Reserved 版权所有•ijava学习网 京ICP备14061482号-18         官方QQ:3325669927

ijava学习网提供免费java教程和大量java面试题库,给高级会员提供免费的java培训,同时提共一些java开发项目和java下载,java工程师,java菜鸟们快来哦。记住我们的网站:www.ijava.com