Linux阻止I / O实际上如何工作?

时间:2010-05-05 22:25:20

标签: linux linux-kernel blocking

在Linux中,当您进行阻止i / o调用时,如读取或接受,实际发生了什么?

我的想法:进程从运行队列中取出,在某个等待队列上进入等待或阻塞状态。然后当建立tcp连接(用于接受)或硬盘驱动器准备就绪或读取文件时,会引发硬件中断,让那些进程等待唤醒并运行(在文件读取的情况下,如何linux知道要唤醒什么进程,因为可能有很多进程在等待不同的文件?)。或者也许不是硬件中断,单个进程本身轮询以检查可用性。不确定,帮忙吗?

3 个答案:

答案 0 :(得分:13)

每个Linux设备的实现似乎略有不同,并且随着更安全/更快的内核功能的添加,首选方式似乎每个Linux版本都有所不同,但通常是:

  1. 设备驱动程序创建读取和 为设备写等待队列。
  2. 任何想要等待的进程线程 对于i / o是适当的 等待队列。发生中断时 处理程序唤醒一个或多个 等待线程。 (显然是 因为我们处于中断状态,线程不会立即运行 上下文,但被添加到 内核的调度队列。)
  3. 由内核安排时 线程检查以查看条件 是否适合继续 - 如果没有 它会回到等待队列上。
  4. 一个典型的例子(略微简化):

    在初始化的驱动程序中:

        init_waitqueue_head(&readers_wait_q);
    

    在驱动程序的读取功能中:

        if (filp->f_flags & O_NONBLOCK)
        {
            return -EAGAIN;
        }
        if (wait_event_interruptible(&readers_wait_q, read_avail != 0))
        {
            /* signal interrupted the wait, return */
            return -ERESTARTSYS;
        }
        to_copy = min(user_max_read, read_avail);
        copy_to_user(user_buf, read_ptr, to_copy);
    

    然后中断处理程序就会发出:

        wake_up_interruptible(&readers_wait_q);
    

    请注意,wait_event_interruptible()是一个隐藏循环的宏,在这种情况下会检查条件 - read_avail != 0 - 如果条件不为真,则会再次重复添加到等待队列。

    如上所述,有许多变体 - 主要的一个是,如果中断处理程序可能有很多工作要做,那么它自己完成最小工作并将其余部分推迟到工作队列或tasklet(通常被称为“下半部分”),这就是唤醒等待的线程。

    有关更多详细信息,请参阅Linux设备驱动程序书 - pdf在此处提供: http://lwn.net/Kernel/LDD3

答案 1 :(得分:0)

阅读本文:http://www.minix3.org/doc/

这是一个非常,清晰,易于理解的解释。它通常也适用于Linux。

答案 2 :(得分:0)

有效地,该方法只会在文件准备好读取,数据在套接字上,连接到达时返回...

为了确保它可以立即返回,您可能希望使用Select系统调用来查找就绪文件描述符。