由于防火墙后面的 NFS 共享,我经常遇到进程陷入 D 状态的问题。如果我失去连接,进程就会陷入 D 状态,我无法杀死它们。唯一的解决方案是硬重启。我想知道是否还有其他方法,但我能找到的所有解决方案和信息都是“你就是杀不了它”。每个人似乎都接受并接受现状。我对此有些批评。我认为必须有一种方法可以从内存中刮掉该进程,这样就不需要重新启动。如果这种情况经常发生,那就非常烦人了。如果资源恰好返回 IO,则在这种情况下可以简单地忽略它。为什么这不可能?恕我直言,Linux 内核非常先进,你应该能够做这样的事情。特别是在服务器中...
我找不到满意的答案,为什么不/不能实施?
我也对有关编程和算法性质的答案感兴趣,这可以解释这个问题。
答案1
在系统调用中杀死进程是可能的,而且大多数情况下都是有效的。困难的是让它始终有效。从 99.99% 到 100% 是困难的部分。
通常,当进程被终止时,它使用的所有资源都会被释放。如果进程中正在进行任何 I/O,则会通知执行此 I/O 的代码并退出,从而释放其正在使用的资源。
当“代码被通知并退出”花费了不可忽略的时间时,不间断的睡眠就会明显地发生。这意味着代码无法正常工作。这是一个错误。是的,理论上可以编写没有错误的代码,但实际上是不可能的。
你说“如果资源碰巧返回 IO,它可以简单地被忽略”。好吧,好吧。但假设外设已被编程为写入内存属于过程。要终止进程而不取消对外围设备的请求,必须以某种方式保持内存使用。您不能直接摆脱该资源。有些资源必须留在身边。只有当内核知道哪些资源可以安全释放时,才能释放其他资源,这需要以始终可以分辨的方式编写代码。不间断睡眠持续明显时间的情况是无法判断的,唯一安全的办法就是避开。
可以设计一个操作系统,保证杀死进程能够正常工作(在硬件正常工作的某些假设下)。例如,硬实时操作系统保证终止进程最多需要一定的固定时间(假设它提供终止功能)。但这很困难,特别是如果操作系统还必须支持广泛的外设并提供良好的常见性能。 Linux 在很多方面都更喜欢常见情况的行为而不是最坏情况的行为。
覆盖所有代码路径是极其困难的,特别是当从第一天开始就没有严格的框架来执行此操作时。从总体上看,不可杀死的进程极其罕见(当它们不发生时您不会注意到) )。这是越野车司机的症状。在编写 Linux 驱动程序方面投入了有限的精力。要消除更多长时间不间断睡眠的情况,要么需要更多的人来执行任务,要么导致支持的硬件更少和性能更差。