14

很明显,通常 read(2) 系统调用可以返回比请求读取的字节少的字节。然而,相当多的程序假设在处理本地文件时,read(2) 永远不会返回少于所要求的内容(当然,除非文件更短)。

所以,我的问题是:在 Linux 上,如果从打开的文件中读取并且没有遇到 EOF 并且正在读取的数量最多为几千字节,那么在哪些情况下 read(2) 返回的值可能少于请求的值?

一些猜测:

  • 接收到的信号可以中断这样的读取,但不会使其失败吗?
  • 不同的文件系统会影响这种行为吗?jffs2有什么特别之处吗?
4

6 回答 6

13

POSIX.1-2008 状态

如果文件中剩余的字节数小于nbyte,如果 read()请求被信号中断,或者文件是管道或 FIFO 或特殊文件并且少于nbyte,则返回的值可能小于 nbyte nbyte字节立即可供读取。

基于磁盘的文件系统通常使用不间断读取,这意味着读取操作通常不能被信号中断。基于网络的文件系统有时会使用可中断的读取,它可以返回部分数据或不返回数据。(在 NFS 的情况下,这可以使用intrmount 选项进行配置。)它们有时也实现超时。

请记住,即使 /some/arbitrary/file/path 也可能指的是 FIFO 或特殊文件,所以您认为的常规文件可能不是。因此,处理部分读取是一种很好的做法,即使它们可能不太可能。

于 2009-12-27T07:59:23.683 回答
3

我不得不问:“你为什么在乎原因”?如果 read 可以返回少于请求数量的字节数(正如您所指出的,它当然可以)为什么您不想处理这种情况?

于 2009-12-27T00:59:55.747 回答
1

接收到的信号仅在尚未读取单个字节时才使 read() 失败。否则,它将返回部分数据。

而且我猜在其他情况下,备用文件系统确实可能会返回短读取。例如,(对我而言)让基于网络的文件系统的行为就像网络套接字 wrt 短读取(= 经常使用它们)是有道理的。

于 2009-12-27T00:56:56.473 回答
1

如果它确实是您正在阅读的文件,那么您可以将短读作为文件结束前的最后一次读取。

但是,通常最好表现得好像任何阅读都可以是短阅读。如果您正在读取的是管道或输入设备(stdin)而不是文件,那么只要您的缓冲区大于输入缓冲区中的当前值,您就可以进行短读取。

于 2009-12-27T01:15:08.217 回答
0

我不确定,但是当操作系统的页面缓存中的页面用完时,可能会出现这种情况。您可以建议在这种情况下调用刷新线程,但这取决于 I/O 调度程序中使用的启发式方法。这种情况可能会导致读取返回更少的字节。

于 2009-12-27T09:22:02.660 回答
0

我一直读到的被称为“短读”的内容与文件访问 read(2) 无关,而是与磁盘扇区的物理读取有关。它发生在读取扇区的数据部分时,发现的有效磁信号少于生成扇区的 512(或 4096 或其他)字节。这会导致无效扇区和读取错误。关于“何时”,或者更确切地说,为什么会发生这种情况,很可能是因为在写入该扇区时驱动器的供电下降了。
可能是 read(2) 以称为“短读”的物理错误代码结尾吗?

于 2018-06-26T17:22:00.990 回答