0%

信号

异步信号

锁、malloc 等不能在信号处理函数里用。这里涉及到 异步信号安全 (async-signal-safe) 的概念。

  1. 信号处理函数的执行环境

当一个信号到达进程时,内核 异步中断当前执行流,立即跳转到信号处理函数执行。

这意味着:

当前线程可能 正在持有锁(mutex、spinlock 等)

当前线程可能 正在使用 malloc/free,操作堆数据结构

  1. 为什么不能调用这些函数

锁(mutex 等)

如果信号处理函数里调用 pthread_mutex_lock():

线程可能已经在信号到达前持有这个锁

信号处理函数再次尝试加锁 → 死锁

malloc / free

malloc 内部会修改全局堆管理结构(如 free list)

如果信号到达时主程序正在调用 malloc 或 free,信号处理函数里再次调用 malloc/free → 堆数据结构可能被破坏

可能导致崩溃或内存泄漏

  1. async-signal-safe 函数

POSIX 定义了一组 “异步信号安全函数”(async-signal-safe functions)

信号处理函数中 只允许调用这些函数

常用安全函数示例:

_exit()

write()(低级系统调用,不会锁堆)

sig_atomic_t 类型变量赋值

总结

函数类型 可在信号处理函数里用? 原因
pthread_mutex_lock 可能已持锁 → 死锁
malloc/free 可能正在操作堆 → 数据结构破坏
write(fd, buf, n) 系统调用,不会破坏用户态结构
_exit() 安全终止进程

核心思想:信号是异步的,中断当前执行流,调用非 async-signal-safe 函数可能破坏正在执行的操作,导致不可预测的行为。