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

当某个进程需要从磁盘中获取数据时,它实际上会停止在CPU上运行以让其他进程运行,因为该操作可能需要很长时间才能完成-至少需要5ms的磁盘寻道时间,而5ms就是1000万从程序的角度来看,CPU周期是永恒的!

从程序员的角度(也称为“在用户空间中”),这称为阻塞系统调用如果您进行调用write(2)(这是同名系统调用周围的薄libc包装器),则您的进程不会完全在该边界处停止;它继续在内核中运行系统调用代码。在大多数情况下,它一直一直到特定的磁盘控制器驱动程序(文件名→文件系统/ VFS→块设备→设备驱动程序),在该驱动程序中,将磁盘上的块获取命令被提交给适当的硬件,这是非常重要的。大多数时候都可以快速操作。

然后,该进程进入睡眠状态(在内核空间中,阻塞称为“睡眠” –从内核的角度来看,没有“阻塞”过)。一旦硬件最终获取了正确的数据,它将被唤醒,然后该过程将被标记为可运行并进行调度。最终,调度程序将运行该过程。

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

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

这里提到D状态TASK_UNINTERRUPTIBLE在Linux状态名称中称为D状态)的大多数答案都是错误的。d状态是一种特殊的睡眠模式,这是只有在内核空间的代码路径,当代码路径引发不能被中断(因为这将是太复杂,程序),并期望它只会阻止了很短时间。我相信大多数“ D状态”实际上是不可见的。它们的寿命很短,无法通过“ top”之类的采样工具来观察。

在某些情况下,您可能会在D状态下遇到无法杀死的进程。NFS为此而闻名,我已经遇到过很多次了。我认为某些VFS代码路径之间存在语义冲突,它们假定始终到达本地磁盘并进行快速错误检测(在SATA上,错误超时将在几百毫秒左右),而NFS实际上从网络中获取数据,更具弹性,恢复速度较慢(TCP超时通常为300秒)。阅读本文了解带有TASK_KILLABLE状态的Linux 2.6.25中引入的出色解决方案在这个时代之前,有一种黑客,您实际上可以通过向内核线程发送SIGKILL来向NFS进程客户端发送信号rpciod,但是请不要理会这个丑陋的把戏。

猜你喜欢

转载自www.cnblogs.com/still-smile/p/12052067.html