【问题标题】:How does read(2) in Linux C work?Linux C 中的 read(2) 是如何工作的?
【发布时间】:2015-05-13 03:59:47
【问题描述】:

根据手册页,我们可以指定要从文件描述符中读取的字节数。

但是在读取的实现中,会创建多少个读取请求来执行读取呢?

例如,如果我想读取 4MB,它会只创建一个 4MB 请求还是将其拆分为多个小请求?比如每个请求 4KB?

【问题讨论】:

  • 在实践中,您最好read 至少有几千字节的缓冲区(大于页面大小,通常为 4K)。您可能应该读入几十 Kb 的缓冲区,例如64 KB。您可以考虑使用mmap(2) 而不是read

标签: c linux system


【解决方案1】:
  • read(2) 是一个系统调用,因此它调用 vDSO 共享库来调度系统调用(在很早以前它曾经是一个中断,但现在有更快的方法来调度系统调用) .

  • 在内核内部,调用首先由 vfs(虚拟文件系统)处理;虚拟文件系统为 inode(表示打开文件的结构)提供通用接口,并提供与底层文件系统接口的通用方式。

  • vfs 分派到底层文件系统(mount(8) 程序会告诉您存在哪个挂载点以及那里使用的文件系统)。 (请参阅此处了解更多信息http://www.inf.fu-berlin.de/lehre/SS01/OS/Lectures/Lecture16.pdf

  • 文件系统可以进行自己的缓存,因此磁盘读取次数取决于缓存中存在的内容以及文件系统如何分配块以存储特定文件以及文件如何划分为磁盘块- 对特定文件系统的所有问题)

  • 如果您想进行自己的缓存,请使用 O_DIRECT 标志打开文件;在这种情况下,努力不使用缓存;但是所有读取都必须对齐到 512 个偏移量并以 512 大小的倍数出现(这是为了您的缓冲区可以通过 DMA 传输到后备存储 http://www.quora.com/Why-does-O_DIRECT-require-I-O-to-be-512-byte-aligned

【讨论】:

    【解决方案2】:

    这取决于你走多远。

    C 库只是在一次 read() 系统调用中将您给它的大小直接传递给内核,因此在该级别它只是一个请求。

    在内核内部,对于标准缓冲模式下的普通文件,您请求的 4MB 将从多个不太可能连续的页面缓存页面(每个 4kB)复制。任何实际上不在页面缓存中的文件数据都必须从磁盘中读取。该文件可能不会连续存储在磁盘上,因此 4MB 可能会导致对底层块设备的多个请求。

    【讨论】:

      【解决方案3】:

      如果有可用数据,read 将立即返回尽可能多的数据,并将其放入缓冲区,无需等待。如果没有可用的数据,它会等到有一些数据,然后返回它可以返回的数据,而不再等待。

      多少取决于文件描述符所指的内容。如果它引用一个套接字,那将是套接字缓冲区中的任何内容。如果它是一个文件,那将是缓冲区缓存中的任何内容。

      【讨论】:

      • 与套接字不同,普通磁盘文件不会返回“短读取”,除非它们到达文件结尾。 POSIX 需要这种行为。
      • 当文件较长时,读取文件返回的数据少于请求的数据是极不寻常的,但并非不可能。
      【解决方案4】:

      当您调用read 时,它只发出一个请求来填充缓冲区大小,如果它无法填充所有缓冲区(没有更多数据或数据没有像套接字一样到达),它会返回字节数它实际上写在你的缓冲区中。

      正如手册所说:

      返回值

      成功完成后,这些函数应返回一个非负整数,指示实际读取的字节数。否则,函数应返回 -1 并设置 errno 以指示 错误。

      【讨论】:

        【解决方案5】:

        真的没有一个正确的答案,除了请求最终到达的任何层都是必要的。通常,单个请求将被传递给内核。这可能导致没有进一步的请求转到其他层,因为所有信息都在内存中。但是,如果必须从软件 RAID 读取数据,则可能必须向多个物理设备发出请求以满足请求。

        我认为你真的不能给出比“实施者认为是最好的方法”更好的答案了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-08
          • 2017-06-25
          • 2014-07-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多