很明显,通常 read(2) 系统调用可以返回比请求读取的字节少的字节。然而,相当多的程序假设在处理本地文件时,read(2) 永远不会返回少于所要求的内容(当然,除非文件更短)。
所以,我的问题是:在 Linux 上,如果从打开的文件中读取并且没有遇到 EOF 并且正在读取的数量最多为几千字节,那么在哪些情况下 read(2) 返回的值可能少于请求的值?
一些猜测:
- 接收到的信号可以中断这样的读取,但不会使其失败吗?
- 不同的文件系统会影响这种行为吗?jffs2有什么特别之处吗?
很明显,通常 read(2) 系统调用可以返回比请求读取的字节少的字节。然而,相当多的程序假设在处理本地文件时,read(2) 永远不会返回少于所要求的内容(当然,除非文件更短)。
所以,我的问题是:在 Linux 上,如果从打开的文件中读取并且没有遇到 EOF 并且正在读取的数量最多为几千字节,那么在哪些情况下 read(2) 返回的值可能少于请求的值?
一些猜测:
如果文件中剩余的字节数小于nbyte,如果 read()请求被信号中断,或者文件是管道或 FIFO 或特殊文件并且少于nbyte,则返回的值可能小于 nbyte nbyte字节立即可供读取。
基于磁盘的文件系统通常使用不间断读取,这意味着读取操作通常不能被信号中断。基于网络的文件系统有时会使用可中断的读取,它可以返回部分数据或不返回数据。(在 NFS 的情况下,这可以使用intr
mount 选项进行配置。)它们有时也实现超时。
请记住,即使 /some/arbitrary/file/path 也可能指的是 FIFO 或特殊文件,所以您认为的常规文件可能不是。因此,处理部分读取是一种很好的做法,即使它们可能不太可能。
我不得不问:“你为什么在乎原因”?如果 read 可以返回少于请求数量的字节数(正如您所指出的,它当然可以)为什么您不想处理这种情况?
接收到的信号仅在尚未读取单个字节时才使 read() 失败。否则,它将返回部分数据。
而且我猜在其他情况下,备用文件系统确实可能会返回短读取。例如,(对我而言)让基于网络的文件系统的行为就像网络套接字 wrt 短读取(= 经常使用它们)是有道理的。
如果它确实是您正在阅读的文件,那么您可以将短读作为文件结束前的最后一次读取。
但是,通常最好表现得好像任何阅读都可以是短阅读。如果您正在读取的是管道或输入设备(stdin)而不是文件,那么只要您的缓冲区大于输入缓冲区中的当前值,您就可以进行短读取。
我不确定,但是当操作系统的页面缓存中的页面用完时,可能会出现这种情况。您可以建议在这种情况下调用刷新线程,但这取决于 I/O 调度程序中使用的启发式方法。这种情况可能会导致读取返回更少的字节。
我一直读到的被称为“短读”的内容与文件访问 read(2) 无关,而是与磁盘扇区的物理读取有关。它发生在读取扇区的数据部分时,发现的有效磁信号少于生成扇区的 512(或 4096 或其他)字节。这会导致无效扇区和读取错误。关于“何时”,或者更确切地说,为什么会发生这种情况,很可能是因为在写入该扇区时驱动器的供电下降了。
可能是 read(2) 以称为“短读”的物理错误代码结尾吗?