有时,每当我在 Linux 中编写程序并且由于某种错误而崩溃时,它将成为一个不可中断的进程并永远运行,直到我重新启动计算机(即使我注销)。我的问题是:
不可中断进程是恰好处于系统调用(内核函数)中且不能被信号中断的进程。
要理解这意味着什么,您需要了解可中断系统调用的概念。经典的例子是read()。这是一个可能需要很长时间(几秒钟)的系统调用,因为它可能涉及旋转硬盘驱动器或移动磁头。在这段时间的大部分时间里,进程将处于休眠状态,在硬件上阻塞。
read()
当进程在系统调用中处于休眠状态时,它可以接收到一个 Unix 异步信号(例如 SIGTERM),然后会发生以下情况:
从系统调用中提前返回使用户空间代码能够立即改变其行为以响应信号。例如,干净地终止以响应 SIGINT 或 SIGTERM。
另一方面,一些系统调用不允许以这种方式被中断。如果系统调用由于某种原因停止,进程可以无限期地保持在这种不可杀死的状态。
LWN 在 7 月份发表了一篇很好的文章,触及了这个话题。
要回答原始问题:
如何防止这种情况发生:找出哪个驱动程序给您带来麻烦,然后停止使用,或者成为内核黑客并修复它。
如何在不重新启动的情况下杀死不可中断的进程:以某种方式使系统调用终止。在不敲击电源开关的情况下执行此操作的最有效方法通常是拉电源线。您也可以成为内核黑客,并让驱动程序使用 TASK_KILLABLE,如 LWN 文章中所述。