sigaction() - Unix 和 Linux 系统调用
Tutorials Point


  Unix 初学者指南
  Unix Shell 编程
  高级 Unix
  Unix 有用参考
  Unix 有用资源
  精选阅读

版权所有 © 2014 tutorialspoint



  首页     参考     讨论论坛     关于 TP  

sigaction() - Unix 和 Linux 系统调用


previous next AddThis Social Bookmark Button

广告

名称

sigaction - 检查和更改信号操作

语法

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

描述

sigaction() 系统调用用于更改进程在收到特定信号时采取的操作。

signum 指定信号,可以是任何有效的信号,除了 SIGKILLSIGSTOP

如果 act 非空,则从 act 安装信号 signum 的新操作。如果 oldact 非空,则将先前操作保存到 oldact 中。

sigaction 结构定义如下

struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
}

在某些体系结构上,涉及联合体:不要同时为 sa_handlersa_sigaction 赋值。

sa_restorer 元素已过时,不应使用。POSIX 未指定 sa_restorer 元素。

sa_handler 指定要与 signum 关联的操作,可以是 SIG_DFL(默认操作),SIG_IGN(忽略此信号),或者是指向信号处理函数的指针。此函数接收信号编号作为其唯一参数。

如果在 sa_flags 中指定了 SA_SIGINFO,则 sa_sigaction(而不是 sa_handler)指定 signum 的信号处理函数。此函数接收信号编号作为其第一个参数,指向 siginfo_t 的指针作为其第二个参数,以及指向 ucontext_t(强制转换为 void *)的指针作为其第三个参数。

sa_mask 给出一个信号掩码,这些信号应在执行信号处理程序期间被阻塞。此外,触发处理程序的信号将被阻塞,除非使用了 SA_NODEFER 标志。

sa_flags 指定一组标志,这些标志修改信号处理过程的行为。它由以下零个或多个标志的按位或组成

标签描述
SA_NOCLDSTOP
 如果 signumSIGCHLD,则在子进程停止(即,当它们收到 SIGSTOPSIGTSTPSIGTTINSIGTTOU 中的一个)或恢复(即,它们收到 SIGCONT)时,不接收通知(参见 wait(2))。
SA_NOCLDWAIT
 (Linux 2.6 及更高版本)如果 signumSIGCHLD,则当子进程终止时,不要将其转换为僵尸进程。另请参见 waitpid(2) 。
SA_RESETHAND
 一旦调用信号处理程序,就将信号操作恢复为默认状态。SA_ONESHOT 是此标志的已过时非标准同义词。
SA_ONSTACK
 sigaltstack(2) 提供的备用信号栈上调用信号处理程序。如果备用栈不可用,则将使用默认栈。
SA_RESTART
 通过使某些系统调用能够跨信号重新启动,提供与 BSD 信号语义兼容的行为。
SA_NODEFER
 不要阻止从其自己的信号处理程序中接收信号。SA_NOMASK 是此标志的已过时非标准同义词。
SA_SIGINFO
 信号处理程序接受 3 个参数,而不是一个。在这种情况下,应设置 sa_sigaction 而不是 sa_handler。(sa_sigaction 字段是在 Linux 2.1.86 中添加的。)

sa_sigactionsiginfo_t 参数是一个具有以下元素的结构

siginfo_t {
    int      si_signo;  /* Signal number */
    int      si_errno;  /* An errno value */
    int      si_code;   /* Signal code */
    pid_t    si_pid;    /* Sending process ID */
    uid_t    si_uid;    /* Real user ID of sending process */
    int      si_status; /* Exit value or signal */
    clock_t  si_utime;  /* User time consumed */
    clock_t  si_stime;  /* System time consumed */
    sigval_t si_value;  /* Signal value */
    int      si_int;    /* POSIX.1b signal */
    void *   si_ptr;    /* POSIX.1b signal */
    void *   si_addr;   /* Memory location which caused fault */
    int      si_band;   /* Band event */
    int      si_fd;     /* File descriptor */
}

si_signosi_errnosi_code 对所有信号都已定义。(si_signo 在 Linux 上未使用。)结构的其余部分可能是一个联合体,因此只能读取对给定信号有意义的字段。POSIX.1b 信号和 SIGCHLD 将填充 si_pidsi_uidSIGCHLD 还填充 si_statussi_utimesi_stimesi_intsi_ptr 由 POSIX.1b 信号的发件人指定。SIGILLSIGFPESIGSEGVSIGBUSsi_addr 填充为错误地址。SIGPOLL 填充 si_bandsi_fd

si_code 指示发送此信号的原因。它是一个值,而不是一个位掩码。任何信号可能出现的值在此表中列出

si_code
信号来源
SI_USERkill()、sigsend() 或 raise()
SI_KERNEL内核
SI_QUEUEsigqueue()
SI_TIMERPOSIX 定时器过期
SI_MESGQPOSIX 消息队列状态更改(自 Linux 2.6.6 起)
SI_ASYNCIOAIO 完成
SI_SIGIO排队的 SIGIO
SI_TKILLtkill() 或 tgkill()(自 Linux 2.4.19 起)

SIGILL
ILL_ILLOPC非法操作码
ILL_ILLOPN非法操作数
ILL_ILLADR非法寻址模式
ILL_ILLTRP非法陷阱
ILL_PRVOPC特权操作码
ILL_PRVREG特权寄存器
ILL_COPROC协处理器错误
ILL_BADSTK内部堆栈错误

SIGFPE
FPE_INTDIV整数除以零
FPE_INTOVF整数溢出
FPE_FLTDIV浮点除以零
FPE_FLTOVF浮点溢出
FPE_FLTUND浮点下溢
FPE_FLTRES浮点结果不精确
FPE_FLTINV浮点无效操作
FPE_FLTSUB下标越界

SIGSEGV
SEGV_MAPERR地址未映射到对象
SEGV_ACCERR映射对象的权限无效

SIGBUS
BUS_ADRALN地址对齐无效
BUS_ADRERR不存在的物理地址
BUS_OBJERR特定于对象的硬件错误

SIGTRAP
TRAP_BRKPT进程断点
TRAP_TRACE进程跟踪陷阱

SIGCHLD
CLD_EXITED子进程已退出
CLD_KILLED子进程被杀死
CLD_DUMPED子进程异常终止
CLD_TRAPPED跟踪的子进程已陷入
CLD_STOPPED子进程已停止
CLD_CONTINUED已停止的子进程已继续(自 Linux 2.6.9 起)

SIGPOLL
POLL_IN数据输入可用
POLL_OUT输出缓冲区可用
POLL_MSG输入消息可用
POLL_ERRI/O 错误
POLL_PRI高优先级输入可用
POLL_HUP设备断开连接

返回值

sigaction() 成功时返回 0,错误时返回 -1。

错误

标签描述
EFAULT actoldact 指向的内存不是进程地址空间的有效部分。
EINVAL 指定了无效信号。如果尝试更改 SIGKILLSIGSTOP 的操作,也会生成此错误,因为这两个信号无法捕获或忽略。

备注

根据 POSIX,进程在忽略了未由 kill() 或 raise() 生成的 SIGFPESIGILLSIGSEGV 信号后的行为未定义。整数除以零的结果未定义。在某些体系结构上,它会生成 SIGFPE 信号。(同样,将最负整数除以 -1 也可能生成 SIGFPE。)忽略此信号可能导致无限循环。

POSIX.1-1990 不允许将 SIGCHLD 的操作设置为 SIG_IGN。POSIX.1-2001 允许这种可能性,以便可以忽略 SIGCHLD 以防止创建僵尸进程(参见 wait(2))。然而,忽略 SIGCHLD 的历史 BSD 和 System V 行为有所不同,因此确保终止的子进程不成为僵尸进程的唯一完全可移植的方法是捕获 SIGCHLD 信号并执行 wait(2) 或类似操作。

POSIX.1-1990 仅指定了 SA_NOCLDSTOP。POSIX.1-2001 添加了 SA_NOCLDWAITSA_RESETHANDSA_NODEFERSA_SIGINFO。在打算用于较旧 Unix 实现的应用程序中,使用 sa_flags 中的这些后几个值的可移植性可能较差。

Linux 2.2 中添加了对 SA_SIGINFO 的支持。

SA_RESETHAND 标志与同名的 SVr4 标志兼容。

SA_NODEFER 标志在内核 1.3.9 及更高版本下与同名的 SVr4 标志兼容。在较旧的内核上,Linux 实现允许接收任何信号,而不仅仅是我们正在安装的信号(有效地覆盖了任何 sa_mask 设置)。

sigaction() 可以使用空第二个参数调用以查询当前信号处理程序。它还可以通过使用空第二个和第三个参数调用它来检查给定信号对于当前机器是否有效。

无法阻止 SIGKILLSIGSTOP(通过在 sa_mask 中指定它们)。对此类尝试会静默忽略。

有关操作信号集的详细信息,请参见 sigsetops(3)。

错误

在内核版本 2.6.13 及之前,在sa_flags中指定SA_NODEFER不仅会阻止在处理程序执行期间屏蔽传递的信号,还会阻止sa_mask中指定的信号。此错误已在内核 2.6.14 中修复。

符合标准

POSIX.1-2001, SVr4。

未公开文档

在引入SA_SIGINFO之前,还可以通过使用第二个参数类型为struct sigcontextsa_handler获取一些其他信息。有关详细信息,请参阅相关的内核源代码。此用法现已过时。

参见



previous next Printer Friendly

广告


  

广告



广告