sigaction() - Unix 和 Linux 系统调用
广告
名称sigaction - 检查和更改信号操作语法
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 描述sigaction() 系统调用用于更改进程在收到特定信号时采取的操作。
signum 指定信号,可以是任何有效的信号,除了 SIGKILL 和 SIGSTOP。 如果 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_handler 和 sa_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 | | 如果 signum 是 SIGCHLD,则在子进程停止(即,当它们收到 SIGSTOP、SIGTSTP、SIGTTIN 或 SIGTTOU 中的一个)或恢复(即,它们收到 SIGCONT)时,不接收通知(参见 wait(2))。 |
SA_NOCLDWAIT | | (Linux 2.6 及更高版本)如果 signum 是 SIGCHLD,则当子进程终止时,不要将其转换为僵尸进程。另请参见 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_sigaction 的 siginfo_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_signo、si_errno 和 si_code 对所有信号都已定义。(si_signo 在 Linux 上未使用。)结构的其余部分可能是一个联合体,因此只能读取对给定信号有意义的字段。POSIX.1b 信号和 SIGCHLD 将填充 si_pid 和 si_uid。SIGCHLD 还填充 si_status、si_utime 和 si_stime。si_int 和 si_ptr 由 POSIX.1b 信号的发件人指定。SIGILL、SIGFPE、SIGSEGV 和 SIGBUS 将 si_addr 填充为错误地址。SIGPOLL 填充 si_band 和 si_fd。
si_code 指示发送此信号的原因。它是一个值,而不是一个位掩码。任何信号可能出现的值在此表中列出
si_code |
值 | 信号来源 |
SI_USER | kill()、sigsend() 或 raise() |
SI_KERNEL | 内核 |
SI_QUEUE | sigqueue() |
SI_TIMER | POSIX 定时器过期 |
SI_MESGQ | POSIX 消息队列状态更改(自 Linux 2.6.6 起) |
SI_ASYNCIO | AIO 完成 |
SI_SIGIO | 排队的 SIGIO |
SI_TKILL | tkill() 或 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_ERR | I/O 错误 |
POLL_PRI | 高优先级输入可用 |
POLL_HUP | 设备断开连接 |
返回值
sigaction() 成功时返回 0,错误时返回 -1。错误
标签 | 描述 |
EFAULT |
act 或 oldact 指向的内存不是进程地址空间的有效部分。 |
EINVAL | 指定了无效信号。如果尝试更改 SIGKILL 或 SIGSTOP 的操作,也会生成此错误,因为这两个信号无法捕获或忽略。 |
备注
根据 POSIX,进程在忽略了未由 kill() 或 raise() 生成的 SIGFPE、SIGILL 或 SIGSEGV 信号后的行为未定义。整数除以零的结果未定义。在某些体系结构上,它会生成 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_NOCLDWAIT、SA_RESETHAND、SA_NODEFER 和 SA_SIGINFO。在打算用于较旧 Unix 实现的应用程序中,使用 sa_flags 中的这些后几个值的可移植性可能较差。 Linux 2.2 中添加了对 SA_SIGINFO 的支持。 SA_RESETHAND 标志与同名的 SVr4 标志兼容。 SA_NODEFER 标志在内核 1.3.9 及更高版本下与同名的 SVr4 标志兼容。在较旧的内核上,Linux 实现允许接收任何信号,而不仅仅是我们正在安装的信号(有效地覆盖了任何 sa_mask 设置)。
sigaction() 可以使用空第二个参数调用以查询当前信号处理程序。它还可以通过使用空第二个和第三个参数调用它来检查给定信号对于当前机器是否有效。 无法阻止 SIGKILL 或 SIGSTOP(通过在 sa_mask 中指定它们)。对此类尝试会静默忽略。 有关操作信号集的详细信息,请参见 sigsetops(3)。 错误
在内核版本 2.6.13 及之前,在sa_flags中指定SA_NODEFER不仅会阻止在处理程序执行期间屏蔽传递的信号,还会阻止sa_mask中指定的信号。此错误已在内核 2.6.14 中修复。符合标准POSIX.1-2001, SVr4。未公开文档在引入SA_SIGINFO之前,还可以通过使用第二个参数类型为struct sigcontext的sa_handler获取一些其他信息。有关详细信息,请参阅相关的内核源代码。此用法现已过时。参见
广告
|