Linux进程状态

Bla*_*air 87 linux cpu kernel process states

在Linux中,当需要从磁盘读取块时,进程状态会发生什么?它被阻止了吗?如果是这样,如何选择执行另一个过程?

zer*_*eux 128

当进程需要从磁盘获取数据时,它会有效地停止在CPU上运行以允许其他进程运行,因为操作可能需要很长时间才能完成 - 至少5ms寻找磁盘的时间是常见的,5ms是1000万CPU周期,从程序的角度来看是永恒的!

从程序员的角度来看(也称"在用户空间"),这称为阻塞系统调用.如果你调用write(2)(这是一个围绕同名系统调用的瘦libc包装器),你的进程并不完全停在该边界; 它继续在内核中运行系统调用代码.大部分时间它一直到特定的磁盘控制器驱动程序(文件名→文件系统/ VFS→块设备→设备驱动程序),其中获取磁盘上的块的命令被提交到适当的硬件,这是一个非常大部分时间都快速操作.

然后,进程处于睡眠状态(在内核空间中,阻塞称为休眠 - 从内核的角度来看,没有任何东西被"阻止").一旦硬件最终获取了正确的数据,它就会被唤醒,然后该进程将被标记为可运行并将被调度.最终,调度程序将运行该过程.

最后,在用户空间中,阻塞系统调用返回正确的状态和数据,程序流继续.

它可以调用大部分的I/O系统调用非阻塞模式(见O_NONBLOCKopen(2)fcntl(2)).在这种情况下,系统立即调用return,仅报告提交磁盘操作.程序员必须在以后明确检查操作是否成功完成,并获取其结果(例如,with select(2)).这称为异步或基于事件的编程.

这里提到D状态(TASK_UNINTERRUPTIBLE在Linux状态名称中调用)的大多数答案都是不正确的.在d状态是一种特殊的睡眠模式,这是只有在内核空间的代码路径,当代码路径引发不能被中断(因为这将是太复杂,程序),并期望它只会阻止了很短时间.我相信大多数"D州"实际上是看不见的; 它们非常短暂,无法通过"顶部"等采样工具观察到.

在某些情况下,您可以在D状态下遇到不可杀死的进程.NFS因此而闻名,我已经多次遇到过它.我认为一些VFS代码路径之间存在语义冲突,它们假设总是到达本地磁盘并且快速检测错误(在SATA上,错误超时将在几百毫秒左右),而NFS实际上从网络中获取数据更具弹性并且恢复缓慢(TCP超时为300秒是常见的).阅读本文,了解Linux 2.6.25中引入的酷炫解决方案TASK_KILLABLE.在这个时代之前有一个hack,你可以通过向内核线程发送一个SIGKILL来实际向NFS进程客户端发送信号rpciod,但是忘掉那个丑陋的技巧....

  • 这个答案是唯一提到NFS的答案,在某些环境中,这是对D状态进程的最常见解释.+1. (20认同)
  • 很好的答案,谢谢.另请注意,进程在等待已换出的页面时进入D状态,因此抖动过程将长时间处于D状态. (14认同)
  • +1的详细回复,但请注意,这个帖子已经接受了近两年的答案.如果您想了解最近的问题,请点击"问题"链接.欢迎来到Stack Overflow,感谢您的贡献! (2认同)

Tim*_*ost 81

在等待read()write()从文件描述符返回时,该过程将被置于一种特殊的睡眠状态,称为"D"或"磁盘睡眠".这是特殊的,因为在这种状态下不能杀死或中断该过程.等待从ioctl()返回的进程也将以这种方式进入休眠状态.

例外情况是文件(例如终端或其他字符设备)在O_NONBLOCK模式下打开,在假定设备(如调制解调器)需要时间初始化时传递.但是,您在问题中指出了阻止设备.此外,我从来没有尝试过一个ioctl()可能会阻止在非阻塞模式下打开的fd(至少不是故意的).

如何选择另一个进程完全取决于您正在使用的调度程序,以及在该调度程序中修改其权重可能采取的其他进程.

已知某些用户空间程序在某些情况下会永远保持此状态,直到重新启动.这些通常与其他"僵尸"分组,但该术语不正确,因为它们在技术上不是已经不存在.


use*_*579 7

执行I/O的进程将进入D状态(不间断休眠),从而释放CPU,直到有硬件中断告诉CPU返回执行程序.请参阅man ps其他过程状态.

根据您的内核,有一个进程调度程序,它可以跟踪准备执行的进程的队列.它与调度算法一起告诉内核将哪个进程分配给哪个CPU.需要考虑内核进程和用户进程.每个进程都分配一个时间片,这是一个允许使用的CPU时间块.一旦进程使用其所有时间片,就会将其标记为已过期,并在调度算法中给予较低的优先级.

2.6内核中,有一个O(1)时间复杂度调度程序,因此无论您运行多少个进程,它都会在恒定时间内分配CPU.它更复杂,因为2.6引入了抢占和CPU负载平衡并不是一个简单的算法.在任何情况下,它都是高效的,并且在您等待I/O时CPU不会保持空闲状态.