Linux C中的read(2)如何工作?

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

但是在读取的实现中,将会创build多less个读取请求来执行读取?

例如,如果我想读取4MB,它会创build一个4MB的请求吗?还是将它分成多个小的请求? 如每个请求4KB?

  • 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-要求IO将被512字节对齐 )

如果有数据可用,读取将返回尽可能多的数据,并且可以放入缓冲区,无需等待。 如果没有可用的数据,它将等待,直到有一些,并返回它可以不等待更多。

多少取决于文件描述符是指什么。 如果它引用一个套接字,那将是什么在套接字缓冲区中。 如果它是一个文件,那将是什么在缓冲区缓存中。

当你调用read ,只需要填充一个请求来填充缓冲区大小,如果不能填充所有的缓冲区(没有更多的数据或数据没有像socket那样到达),它将返回实际写入的字节数缓冲。

正如手册所说:

返回值

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

这取决于你有多深。

C库只是在一个read()系统调用中把你给它的大小直接传递给内核,所以在这个层次上它只是一个请求。

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

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

我不认为你可以给出比“实施者认为是最好的方式”更好的答案。