struct sigaction

来源:undefined 2025-06-02 08:43:13 0

struct sigaction 是在 UNIX 和类 UNIX 操作系统(如 Linux)中用于信号处理的一个重要结构体。信号是操作系统和进程之间的一种通信机制,可以用来通知进程发生了某种事件,例如用户按下了中断键(通常是 Ctrl+C),某个进程试图访问非法内存区域等。

在 Linux 系统中,每一个信号都有一个默认的处理方式,但有时候程序开发者希望改变信号的默认处理行为,例如,在收到某个特定信号时执行一个特定的函数。为了实现这一需求,提供了 struct sigaction 结构体通过 sigaction() 系统调用为信号设置信号处理程序。

struct sigaction 的定义

在 POSIX.1 标准中,struct sigaction 通常被定义在 <signal.h> 头文件中,定义可能因操作系统不同而略有差异。但通常,该结构体包括以下成员:

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:

类型为函数指针,指向用户定义的信号处理函数。这个函数接受一个 int 类型参数,即信号的编号。 如果设置为 SIG_IGN,表示忽略该信号。 如果设置为 SIG_DFL,则表示使用该信号的默认处理方式。

sa_sigaction:

这是一个替代的信号处理程序,与 sa_handler 互斥。它可以提供信号的更多信息。例如,信号的来源等。 使用 sa_sigaction 需要同时设置 sa_flags 的 SA_SIGINFO 标志。

sa_mask:

这是一个信号集,在信号处理程序执行期间需要被阻塞的信号集合。 它可以防止处理特定信号时被其他信号中断。

sa_flags:

这是一个整型值,用于指定信号处理的行为,可以用不同的标志组合来修改处理行为。 常见的标志包括: SA_RESTART: 使被中断的系统调用自动重新启动。 SA_NOCLDSTOP: 子进程停止时不产生 SIGCHLD 信号。 SA_NOCLDWAIT: 子进程退出时不创建僵尸进程。 SA_NODEFER: 允许在处理信号时递归处理该信号。 SA_SIGINFO: 使用 sa_sigaction 而不是 sa_handler 作为信号处理程序。

sa_restorer:

在现代实现中通常未使用。在一些系统中可能用于指定一个在完成信号处理后恢复上下文的函数。

使用 sigaction 函数

为了设置信号处理程序,需要使用 sigaction() 系统调用,函数原型如下:

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); signum: 信号编号,例如 SIGINT。 act: 指向一个 struct sigaction 的指针,描述如何处理该信号。 oldact: 如果不为 NULL,则用于保存先前的信号处理设置信息。

示例

以下是一个简单的使用 sigaction 设置信号处理程序的示例:

#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> void handler(int signum) { printf("Received signal %d ", signum); } int main() { struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = handler; act.sa_flags = SA_RESTART; // 自动重新启动被中断的系统调用 if (sigaction(SIGINT, &act, NULL) < 0) { perror("sigaction"); exit(EXIT_FAILURE); } printf("Press Ctrl+C to trigger SIGINT... "); while (1) { pause(); // 等待信号 } return 0; }

在该示例中,信号处理程序 handler 将会在 SIGINT 信号(如 Ctrl+C)发送到进程时被调用。信号处理程序只是简单地打印接收到的信号编号。

sigaction vs signal

很多初学者会疑惑 sigaction 与传统的 signal 函数的区别,signal 是一种更简单直观的 API,但 sigaction 提供了更强大和灵活的信号处理功能,特别是在控制信号屏蔽、支持多个信号处理模式(通过标志选项)以及避免信号处理中的竞态条件等方面。

综上所述,struct sigaction 和 sigaction() 系统调用构成了 UNIX 系统中信号处理的基石,可以帮助开发者细粒度地控制信号处理,使应用程序更稳定和安全。这也反映了 UNIX 哲学中给用户提供原动力和灵活性的设计理念。

最新文章