在Linux中,会发生什么情况的过程的状态时,它需要从磁盘中读取的块? 难道受阻? 如果是这样,怎么另一个进程选择了执行呢?
Answer 1:
在等待read()
或write()
从文件描述符返回/,该过程将被放置在一个特殊的睡眠,被称为“d”或“磁盘休眠”。 这是特殊的,因为过程中不能同时在这种状态下被杀死或中断。 等待的ioctl()返回的处理也将被放在这种方式睡觉。
当一个文件(如一个终端或其它字符设备)中被打开以一个例外是O_NONBLOCK
模式,通过假设其时,一个设备(如调制解调器)将需要的时间进行初始化。 但是,你在你的问题表示块设备。 另外,我从未尝试过的ioctl()
很可能阻塞的Fd在非阻塞模式下打开(至少不会有意)。
如何选择另一个进程完全取决于调度您使用,以及什么其他进程可能会做的到调度中修改它们的权重。
在某些情况下一些用户空间程序已经知道保持这种状态永远,直到重新启动。 这些通常编组与其他“植物大战僵尸”,但因为它们不是技术上已不存在的任期将是不正确的。
Answer 2:
当一个进程需要从磁盘中读取数据时,它有效地停止在CPU上运行,让其他进程运行,因为该操作可能需要很长时间才能完成 - 至少5毫秒的寻道时间的磁盘是常见的,而5ms的1000万CPU周期,从程序的角度永恒!
从视程序员点(也称“用户空间”),这就是所谓的阻塞系统调用 。 如果调用write(2)
这大约是相同名称的系统调用薄的libc包装),你的进程并不完全停止在该边界; 再这样下去,在内核,运行系统调用代码。 大部分它去一路到特定的磁盘控制器驱动程序(文件名→文件系统/ VFS→块设备→设备驱动器),其中一个命令被提交给适当的硬件,这是一个非常取盘上的块的时间快速运行的大部分时间。
然后,该过程被置于休眠状态 (在内核空间,阻断被称为睡眠-但从核心点没有什么是永远“阻塞”)。 一旦硬件终于获取正确的数据,则该过程将被标记为可运行 ,并会安排将被唤醒。 最终,调度程序将运行的过程。
最后,在用户空间,在适当的状态和数据,程序流程阻塞系统调用返回的推移。
能够调用大多数I / O系统中非阻塞模式调用(参见O_NONBLOCK
在open(2)
和fcntl(2)
在这种情况下,系统调用,并立即提交唯一的磁盘操作报告返回。 程序员必须明确检查以后的操作是否完成,成功与否,并获取其结果(例如, select(2)
这就是所谓的异步或基于事件的编程。
大多数的答案在这里提d状态 (被称为TASK_UNINTERRUPTIBLE
在Linux状态的名字)是不正确的。 在d状态是一种特殊的睡眠模式,这是只有在内核空间的代码路径,当代码路径不能被中断 (因为这将是太复杂,程序)触发,并期望它只会阻止了很短时间。 我相信大多数“d状态”实际上是看不见的; 他们是非常短暂的,不能由采样工具,如“顶”来观察。
你可以遇到一些情况下,在d状态无法终止的进程。 NFS是著名的,和我遇到了很多次。 我觉得有一些VFS的代码路径,即假定总是达到本地磁盘和快速的错误检测之间的语义冲突(上SATA,错误超时将围绕几个100毫秒)和NFS,这实际上从网络上获取数据,是更有弹性,并且具有缓慢恢复(300秒的TCP超时是常见)。 阅读这篇文章在Linux的2.6.25与引入的溶液冷却TASK_KILLABLE
状态。 这个时代之前有一个黑客,你实际上可以通过发送SIGKILL内核线程发送信号到NFS客户端的过程rpciod
,但忘了那个丑陋的伎俩。...
Answer 3:
执行I / O的方法,将被放置在d状态(不间断睡眠),这将释放CPU,直到有中断它告诉CPU返回到执行该程序的硬件。 见man ps
为其他过程状态。
根据你的内核,有一个过程的调度 ,其跟踪的过程准备好执行运行队列中。 它与调度算法一起,讲述分配给哪个CPU哪个进程的内核。 有内核进程和用户进程来考虑。 每个进程被分配时间片,这是它允许使用的CPU时间的组块。 一旦该过程使用的所有它的时间片的,它被标记为过期,并在调度算法给予较低的优先级。
在2.6内核 ,有一个O(1)的时间复杂度调度 ,所以无论你有多少进程都运行起来,它会分配在固定时间内的CPU。 这是更复杂的,虽然,因为2.6引入了抢占CPU的负载平衡不是一件容易的算法。 在任何情况下,它的高效,而你等待I / O的CPU也不会闲着。
Answer 4:
正如已经被别人解释说,在“d”状态(不间断睡眠)过程负责PS处理的窍门。 对我来说,已经发生与RedHat 6.x系统多次自动挂载NFS主目录。
要列出d状态,您可以使用下面的命令过程:
cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D
要知道进程的当前目录,可能是,有可以使用类似于下面的示例的命令问题NFS安装盘(与睡眠进程数替换31134):
# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug 2 16:25 /proc/31134/cwd -> /auto/pippo
我发现,给使用-f umount命令(力)开关,有关安装的NFS文件系统,能够唤醒沉睡的过程:
umount -f /auto/pippo
文件系统没有卸载,因为它是忙,但相关的过程确实唤醒,我能解决这个问题,无需重新启动。
Answer 5:
假设你的过程是一个单独的线程,而且你使用的是阻塞I / O,你的进程将阻止等待I / O完成。 内核将选择另一个进程的基础上美好的事物,优先级,上次运行时间等,如果没有其他可运行进程,内核将不会运行任何同时运行; 相反,它会告诉硬件的设备处于闲置状态(这将导致较低的功耗)。
正在等待I / O办法通常进程在状态d,例如,出现ps
和top
。
Answer 6:
是的,这个任务被挡在了阅读()系统调用。 另一项任务是准备好运行,或者如果没有其他任务准备,空闲任务(针对CPU)运行。
一个正常的,阻挡盘读取导致进入“d”状态(正如其他人指出的)任务。 这些任务有助于平均负载,即使他们不占用CPU。
一些其他类型的IO,特别是ttys中和网络,不要表现得不太一样 - 的过程中“S”的状态结束,且可以中断和不计入平均负载。
Answer 7:
是的,等待IO任务被阻挡,而其他任务得到执行。 在选择下一个任务是由做Linux调度 。
Answer 8:
一般来说,过程将阻止。 如果读操作是在标记为非阻塞一个文件描述符或如果该进程使用异步IO它将不会阻碍。 此外,如果过程中有没有被堵塞,他们可以继续运行其他线程。
哪个进程下一个运行的决定要由调度器在内核中。