直接回答:信号是内核向进程投递的异步事件通知,可理解为"软件中断"。信号可以由内核(如段错误发 SIGSEGV)、其他进程(kill 系统调用)或终端事件(Ctrl+C 发 SIGINT)产生;内核在进程从内核态返回用户态之前检查 pending 信号队列,若有待处理信号,就修改用户态栈帧,让进程先执行信号处理函数,再 sigreturn 恢复原上下文。
展开解析:1~31 号是非可靠信号:不排队,同类信号多个到达会合并丢失;34 号以上是实时信号:排队、可按序到达、能携带一个整型/指针数据。SIGKILL 和 SIGSTOP 不可捕获、不可阻塞、不可忽略,这是系统保留的"最后手段"。注册处理函数应该用 sigaction 而不是 signal,后者语义随平台不一致。
实践要点:处理函数里只能调用异步信号安全(async-signal-safe)的函数,如 write、_exit;调 printf、malloc 很危险——信号可能打断主流程持有 malloc 内部锁的瞬间,handler 再次进入 malloc 就死锁。惯用做法是 handler 里只设置一个 volatile sig_atomic_t 标志,或往 self-pipe 写一个字节,主循环里再做真正的清理。
追问方向:多线程程序里信号发给哪个线程?如何让进程收到 SIGTERM 后优雅退出?为什么 fork 之后、exec 之前只能调 async-signal-safe 函数?