
Coursebook信号章完整教程从发送信号到处理信号【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebookcoursebook是伊利诺伊大学 CS341 使用的开源系统编程教程system programming textbook其中的信号章Signals chapter是 Linux 初学者理解信号机制的必读教程。本文带你走一遍从发送信号到处理信号的完整流程如何用 CTRL-C 或 kill 命令发送信号、内核如何让信号走完生成 → 挂起 → 递送的生命周期、以及如何用 sigaction 与信号标志位写出安全的信号处理器——一份面向新手的信号处理完整指南。 快速了解信号是什么信号signal是一种异步事件通知一个进程可以向另一个进程发送你该注意某件事了的低优先级消息接收方可以选择执行自定义动作、忽略或直接终止。教材将其定位为终止与清理机制不建议把信号当作业务逻辑的驱动。理解信号处理只需要两个核心概念概念作用信号处置disposition每个进程的信号-动作对照表终止、忽略、生成 core dump、停止、继续或执行自定义函数信号掩码mask决定某个信号是否被递送blocked 的信号会挂在 pending 状态等待一个关键事实SIGKILL 和 SIGSTOP 永远无法被捕获、阻塞或忽略。常用信号一览来自教材 POSIX 信号表信号编号默认动作典型用途SIGINT2终止可捕获优雅地停止进程即 CTRL-CSIGQUIT3终止可捕获较粗暴地停止进程SIGTERM15终止进程要求进程退出SIGSTOP—停止进程不可捕获挂起进程SIGCONT—继续进程从挂起中恢复SIGKILL9立即终止不可捕获必须让进程消失时使用 三种方式发送信号CTRL-C、kill 命令、系统事件教材总结了信号产生的三个来源覆盖了你日常会用到的全部场景用户手动发送在终端按下CTRL-C就是发送SIGINT也可以用kill命令按 PID 发送任意信号killall则按进程名匹配。先用ps找到目标 PID 再发送是标准操作。系统/内核发送进程访问了不该访问的内存页时硬件中断被内核拦截内核向肇事进程发送SIGSEGV。子进程创建、进程需要恢复等内核事件也会产生信号。另一个进程发送C 程序可以用 POSIXkill()调用给子进程发信号如SIGUSR1、SIGTERM用raise()或kill(getpid(), sig)给自己发信号。⚠️ 两个易错点非 root 用户只能向同用户的进程发信号你不能随意SIGKILL别人的进程。用SIGSTOP可暂停进程不再分配 CPU 时间用SIGCONT恢复。关于kill -9教材引用了经典 Unix 社区名言不要动不动就kill -9——它不给进程清理 socket、临时文件、通知子进程的机会。建议顺序是先发 15SIGTERM等一两秒不行再发 2再不行发 1。真正顽固的进程才轮到kill -9。另外教材特别提醒不要依赖信号做进程间通信。信号有丢信号、无序等缺点真正需要通信时请使用专用的 IPC 手段管道就是典型代表 信号生命周期从生成到递送的四段路内核处理一个信号的完整流程教材原文流程Generated生成信号被创建Pending挂起从生成到内核应用掩码规则之间的窗口期Blocked阻塞若进程所有线程都在阻塞该信号信号就挂在 pending 等待Delivered递送只要有一个线程可以接受内核就中断该线程正在做的事跳转到信号处理函数处理期间其他信号可生成但不能递送Caught / Killed捕获 / 终止处理完进程安然无恙即捕获若执行默认终止动作则进程被杀。教材为这套流程绘制了信号生命周期流程图signals/drawings/signal_lifecycle.png是本章节的核心示意图。️ 如何安全地处理信号标志位 sigaction这是信号章最有坑的部分。绝大多数库函数和系统调用都是 **async-signal-unsafe异步信号不安全**的信号可能在函数执行到一半时打断你再次进入同一函数就会破坏状态比如共享缓冲区被覆盖打印出错误的值。教材给出的安全设计模式是只设标志不做事信号处理函数里只置位一个标志变量主循环检查该标志后再执行清理。并且标志变量必须声明为volatile sig_atomic_t类型——volatile阻止编译器把循环条件优化成常量、sig_atomic_t保证读写是原子操作这是写出可移植代码的关键。安装处理器时请优先使用sigaction而不是signalsignal在不同操作系统上语义不一致而sigaction语义明确、可移植性更好还能配置sa_mask处理函数执行期间临时阻塞的信号集SA_RESTART被信号打断的系统调用自动重启省去手动重启循环。⏸️ 如何阻塞信号sigprocmask 与 sigwaitsigprocmask用于设置信号掩码三种模式SIG_BLOCK追加阻塞、SIG_UNBLOCK解除阻塞、SIG_SETMASK整体替换。教材点名的高频错误忘记初始化信号集就sigaddset。正确姿势是先sigemptyset()全不阻塞或sigfillset()全阻塞。sigwait是同步等待方式阻塞直到收到指定集合中的一个信号再返回。多线程程序的经典做法是开一个专职信号线程——先用pthread_sigmask在所有线程中阻塞目标信号新建线程会继承掩码信号线程里循环调用sigwait逐个接收。好处是信号逻辑跑在普通线程里可以放心使用几乎所有 C 库函数绕开了 async-signal-unsafe 的限制。 子进程与线程中的信号行为这部分是 fork/exec 知识在信号上的延伸面试和实战都常考fork 之后子进程继承父进程的处置表和掩码的副本但挂起pending信号不继承exec 之后处理器被重置为默认动作旧代码可能已消失掩码和挂起信号保留多线程每个线程有自己的掩码信号可被任何愿意接收的线程捕获选哪个线程是任意的。最佳实践是只留一个线程接收所有信号进程内部可用pthread_kill定向发给某个线程注意对任意线程发SIGKILL都会杀掉整个进程。 学习资源与延伸阅读路径信号章完整源码signals/signals.tex参考资料signals/signals.bib全书章节顺序定义order.yaml信号章排在 IPC、调度之后是系统编程核心话题的收官章节之一相关章节延伸阅读线程 threads/threads.tex、进程间通信 ipc/ipc.tex、死锁 deadlock/deadlock.tex书籍入口与构建说明main.tex、README.md课程覆盖从进程、线程、同步到死锁的完整系统编程知识体系而信号章正是让程序体面地退出与恢复的关键一环。建议先读完本章的理论部分再在终端亲手用kill、ps配合一个简单 C 程序验证 SIGSTOP/SIGCONT 的效果从发送信号到处理信号一小时就能建立完整的信号心智模型。【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考