本文档汇总Linux信号编程核心函数,按「信号发送、信号集操作、信号处理、信号状态管理、辅助工具」分类,配套关键说明、避坑要点及参数补充,精准适配信号机制原理,助力快速开发、调试与问题排查。
一、信号发送函数(主动触发信号)
用于主动向进程发送指定信号,覆盖自身、目标进程、同组进程等场景,是信号编程中触发事件的核心接口。
| 函数原型 | 核心功能 | 关键参数说明 | 返回值 | 备注(避坑要点) |
|---|---|---|---|---|
int kill(pid_t pid, int signo) |
向指定PID进程发送信号 | pid:进程ID(-1表示同组所有进程;0表示同组进程);signo:信号编号(如SIGINT) | 成功返回0,失败返回-1 | 无法向init进程(PID=1)发送SIGKILL(9)/SIGSTOP(19),权限被内核限制 |
int raise(int signo) |
向当前进程发送信号 | signo:需发送的信号编号(有效范围1~64) | 成功返回0,失败返回-1 | 等价于kill(getpid(), signo),仅作用于调用进程自身,逻辑更简洁 |
void abort(void) |
向当前进程发送SIGABRT信号 | 无参数,无需手动指定信号 | 无返回值(必然终止进程,不可规避) | 会触发Core Dump(核心转储),且信号不可被忽略、捕捉或阻塞 |
unsigned int alarm(unsigned int seconds) |
设定闹钟,超时后发送SIGALRM信号 | seconds:超时秒数(0表示取消已设定的闹钟) | 返回旧闹钟剩余秒数,无旧闹钟则返回0 | 同一进程仅一个闹钟生效,新闹钟会直接覆盖旧闹钟,无叠加效果 |
二、信号集操作函数(sigset_t管理)
sigset_t为信号集专用类型,底层是位图结构,不可直接通过位运算操作,必须使用以下函数初始化和管理,初始化是后续操作的前提,否则信号集状态不确定会导致异常。
| 函数原型 | 核心功能 | 关键参数说明 | 返回值 | 备注(避坑要点) |
|---|---|---|---|---|
int sigemptyset(sigset_t *set) |
初始化信号集,所有bit置0(空集) | set:待初始化的信号集指针,需提前定义变量 | 成功返回0,失败返回-1 | 使用sigset_t变量前必须先调用,否则变量内存残留值会导致操作异常 |
int sigfillset(sigset_t *set) |
初始化信号集,所有bit置1(包含所有信号) | set:待初始化的信号集指针 | 成功返回0,失败返回-1 | 初始化后需用sigdelset删除不需要的信号,按需筛选目标信号 |
int sigaddset(sigset_t *set, int signo) |
向信号集添加指定信号(对应bit置1) | set:信号集指针;signo:需添加的信号编号(1~64) | 成功返回0,失败返回-1 | 仅支持添加1~64号有效信号,添加非法编号会返回失败 |
int sigdelset(sigset_t *set, int signo) |
从信号集删除指定信号(对应bit置0) | set:信号集指针;signo:需删除的信号编号 | 成功返回0,失败返回-1 | 删除不存在的信号会返回错误,可先用sigismember验证信号是否在集内 |
int sigismember(const sigset_t *set, int signo) |
判断信号是否在目标信号集中 | set:信号集指针;signo:待判断的信号编号 | 存在返回1,不存在返回0,失败返回-1 | 常用于验证信号集操作结果,避免无效添加/删除操作 |
三、信号处理函数(注册信号响应动作)
用于注册进程收到信号后的响应动作,支持忽略、默认处理、自定义捕捉三种模式,sigaction为POSIX标准函数,兼容性和功能完整性优于signal,推荐优先使用。
| 函数原型 | 核心功能 | 关键参数说明 | 返回值 | 备注(避坑要点) |
|---|---|---|---|---|
void (*signal(int signo, void (*handler)(int)))(int) |
简单注册信号处理函数 | signo:信号编号;handler:处理函数(SIG_IGN/SIG_DFL/自定义函数) | 成功返回旧处理函数,失败返回SIG_ERR | 跨UNIX系统行为不一致,信号处理后可能自动恢复默认动作,推荐用sigaction替代 |
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact) |
标准注册信号处理动作(推荐使用) | signo:信号编号;act:新处理动作;oact:保存旧动作(可设为NULL) | 成功返回0,失败返回-1 | 支持设置处理时阻塞集,避免信号嵌套触发,行为稳定且跨系统兼容 |
| struct sigaction结构体核心字段说明(信号处理精细化配置): |
C
struct sigaction {
void (*sa_handler)(int); // 信号处理函数(同signal,支持SIG_IGN/SIG_DFL/自定义)
sigset_t sa_mask; // 处理信号时额外阻塞的信号集,避免并发干扰
int sa_flags; // 处理选项(通常设为0,采用默认行为,无特殊需求不修改)
};
四、信号状态管理函数(阻塞/未决状态控制)
用于控制信号的阻塞状态(屏蔽字)和读取未决状态,是信号生命周期管理的核心接口,可实现信号的延迟处理、状态查询等功能。
| 函数原型 | 核心功能 | 关键参数说明 | 返回值 | 备注(避坑要点) |
|---|---|---|---|---|
int sigprocmask(int how, const sigset_t *set, sigset_t *oset) |
修改/读取进程信号屏蔽字(阻塞集) | how:修改方式;set:新屏蔽集(NULL表示仅读取);oset:保存旧屏蔽集(NULL表示不保存) | 成功返回0,失败返回-1 | how取值决定操作逻辑,具体见下文参数补充,不可传入非法值 |
int sigpending(sigset_t *set) |
读取当前进程未决信号集 | set:存储未决信号集的指针,需提前初始化 | 成功返回0,失败返回-1 | 仅能读取本进程未决信号,无法修改,常用于调试信号阻塞状态 |
int sigsuspend(const sigset_t *mask) |
临时替换屏蔽字并阻塞等待信号 | mask:临时屏蔽集,信号唤醒后恢复原屏蔽字 | 被信号唤醒后返回-1,errno设为EINTR | 原子操作,避免"读取信号状态-等待信号"的竞争问题,比sleep更安全 |
五、辅助函数(僵尸进程清理)
配合SIGCHLD信号使用,用于清理子进程终止后的僵尸进程,避免系统资源泄漏,是父子进程编程中的常用工具。
| 函数原型 | 核心功能 | 关键参数说明 | 返回值 | 备注(避坑要点) |
|---|---|---|---|---|
pid_t waitpid(pid_t pid, int *status, int options) |
等待子进程终止,清理僵尸进程 | pid:子进程ID(-1表示等待所有子进程);status:存储退出状态;options:等待选项 | 成功返回子进程PID,失败返回-1 | 常用WNOHANG选项实现非阻塞等待,配合SIGCHLD信号可实现子进程自动清理 |
六、核心参数补充(how取值/特殊常量)
1. sigprocmask函数how参数取值
| how取值 | 功能说明 | 等价逻辑(mask为当前屏蔽字) |
|---|---|---|
| SIG_BLOCK | 添加阻塞信号,将set中的信号加入屏蔽字 | mask = mask |
| SIG_UNBLOCK | 解除阻塞信号,将set中的信号从屏蔽字移除 | mask = mask & ~set(按位与非,取消指定信号阻塞) |
| SIG_SETMASK | 直接替换屏蔽字为set,覆盖原有配置 | mask = set(直接赋值,完全替换旧屏蔽字) |
2. 特殊常量说明
-
SIG_IGN:忽略信号,信号递达后不执行任何动作,内核直接清除该信号
-
SIG_DFL:执行信号默认动作,不同信号默认动作不同(如终止、Core Dump、暂停等)
-
SIG_ERR:signal函数返回的错误标识,用于判断信号注册是否失败
七、使用核心原则(避坑核心)
-
信号处理函数需调用可重入函数,避免访问全局/静态变量(若必须访问,需加volatile关键字保证可见性),禁止调用malloc/free和标准I/O函数(如printf),防止数据错乱。
-
SIGKILL(9号)和SIGSTOP(19号)是特殊信号,不可被捕捉、忽略或阻塞,仅能执行默认动作,是强制终止/暂停进程的终极手段。
-
常规信号(131号)不支持排队,重复产生的信号仅递达一次,若需可靠通知,需使用实时信号(3464号)。
-
fork创建子进程后,子进程会继承父进程的信号屏蔽字、未决信号集和处理动作,父进程后续修改信号配置不会影响已创建的子进程。
-
信号处理期间,当前信号会被自动阻塞(内核默认行为),可通过sigaction的sa_mask字段添加额外阻塞信号,避免并发信号干扰。