【问题标题】:"short read" from filesystem, when can it happen?从文件系统“短读”,什么时候会发生?
【发布时间】:2010-12-30 04:55:18
【问题描述】:

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

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

一些猜测:

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

【问题讨论】:

  • 哪些程序“假设在处理本地文件时,read(2) 的返回值永远不会低于所要求的值”?在一般情况下,这听起来像是一个错误。
  • 例如 klibc utils 中的 fstype binary。似乎许多可以假设直接处理文件的低级程序都假设读取永远不会短。

标签: c linux filesystems system-calls


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      POSIX.1-2008 states:

      返回的值可能小于 nbyte 如果剩下的字节数 文件小于 nbyte,如果 read() 请求被一个 信号,或者如果文件是管道或 先进先出或特殊文件,具有较少 超过 nbyte 个字节立即可用 供阅读。

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

      请记住,即使 /some/arbitrary/file/path 也可能指的是 FIFO 或 特殊文件,所以你认为是普通文件的可能不是。因此是 处理部分读取的良好做法,即使它们不太可能发生。

      【讨论】:

      • 谢谢。如果这是正确的,那么我们还有更多的调试要做。我们在 jffs2 文件系统上得到确认的短读取(我猜它不应该有可中断的读取),并且该文件绝对是一个常规文件。这种情况每年最多发生一次,因此重现性很低。
      • 文件系统被允许在读取一个块后中断读取本身。
      【解决方案4】:

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

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

      【讨论】:

      • 我没有遇到 EOF 的意思正是它不是文件结束前的最后一次读取。此外,有问题的文件是常规文件。
      【解决方案5】:

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

      【讨论】:

      • 要添加,您无论如何都要检查数据 - 所以如果它很短,您会立即知道。不然,还有什么读书的理由?
      • 尼尔,我不得不问:你为什么关心他为什么想知道这怎么会发生?即使他处理这种情况,知道它是如何发生的仍然非常有帮助,例如。这样他就可以尝试并测试他的代码是否按预期处理它。如果不是他自己的个人代码没有处理这种情况,则需要此信息作为重现问题的说明的一部分,该问题应伴随任何错误报告或补丁提交。
      • 我问的原因是我们在数千个系统的安装基础上看到了这种行为,我们需要尽可能准确地评估这个问题在很长一段时间内可能有多普遍跑步。了解其发生方式或原因是调查的一部分。
      • 处理短读是新编写代码的好习惯。不过,假设一切都处理来自所有“文件”的短读是非常危险的。大多数公司都有旧代码,其中充满了您甚至不想阅读的内容。不幸的是,在许多第三方库中,不处理短读也是一种非常常见的模式。因此,知道什么时候会发生这种情况几乎毫无用处,因为它可以帮助您知道在哪里会出现问题。
      【解决方案6】:

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

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

      【讨论】:

      • 谢谢,这很有帮助!尽管有关可中断和不可中断文件系统的信息更有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 2012-01-08
      • 1970-01-01
      • 2011-07-23
      相关资源
      最近更新 更多