【问题标题】:read() from files - blocking vs. non-blocking behavior从文件中读取() - 阻塞与非阻塞行为
【发布时间】:2012-04-16 17:20:17
【问题描述】:

假设我们使用fopen() 打开了一个文件,并从收到的文件指针中使用fileno() 获取文件描述符。然后我们从这个文件中做很多(>10^8)随机的read()s 相对小的块,大小在 4Bytes 到 10KBytes 之间:

如果文件系统是一个errno,那么在不设置errno的情况下,read()这样的预期行为是否可能返回比请求更少的字节数

  1. ext3

  2. NFS

  3. OCFS2

  4. 2 和 3 的组合(OCFS2 通过NFS

?

我的读数给了我一个结论,它不应该是 1.(如果文件没有设置 O_NONBLOCK,如果可能的话,ext3 设置它)但对于其他三个(2., 3 ., 4.) 我不确定。

(顺便说一句:我可以假设在任何情况下都没有将O_NONBLOCK 设置为默认值吗?)

之所以出现这个问题,是因为我观察到 read()s 返回的字节数少于在案例 4 中未设置 errno 的情况下请求的字节数。

通过测试深入研究的问题是,这种行为发生在

更新:平均文件大小在几 TBytes 和大约 1GByte 之间。

【问题讨论】:

  • 明显的情况是在文件的末尾,它可能不是请求大小的倍数。 (另外,O_NONBLOCK 不在常规文件上实现)
  • 哦,是的,文件结尾的情况太明显了,我忘了说我不是指的是这个情况...... - 感谢关于O_NONBLOCK! @nos

标签: c linux nfs ocfs2


【解决方案1】:

您不应该假设 read() 不会返回比任何文件系统请求的字节少。在大读取的情况下尤其如此,因为 POSIX.1 表明大于 SSIZE_MAX 的大小的 read() 行为取决于实现。在我现在使用的这个主流 Unix 机器上,SSIZE_MAX 是 32767 字节。 read() 今天总是返回全部金额这一事实并不意味着它将来会。

一个可能的原因可能是 I/O 优先级将来会在内核中更加充实。例如。您正在尝试从与另一个更高优先级进程相同的设备读取数据,并且如果您的进程没有导致头部移动远离另一个进程想要的扇区,那么另一个进程将获得更好的吞吐量。内核可能会选择给你的 read() 一个简短的计数来让你暂时离开,而不是继续进行低效的交错块读取。 Stranger things have been done 为了 I/O 效率。不被禁止的往往变成强制性的。

【讨论】:

  • 非常感谢您的回答。它让我意识到在读取数据的大小方面使用了误导性的词。我现在会纠正这个。
【解决方案2】:

我们解决了所描述的问题,即当从位于NFS 挂载上的文件读取时,read() 返回的字节数少于请求,指向OCFS2 文件系统(我的问题中的案例 4)。

事实上,使用上面提到的设置,文件描述符上的read()s 有时返回的字节数少于请求的字节数,而没有设置errno

要读取所有数据,只需read()一遍又一遍,直到读取所需的数据量。

此外,这种设置有时会使read() 失败并显示EIO,即使这样,简单的重新read() 也会导致成功并且数据到达。

我的结论:通过OCFS2 通过NFS 读取使得来自文件的read()ing 的行为类似于来自套接字的read()ing,这与read() http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html 的规范不一致:

当试图读取一个文件(管道或 FIFO 除外)时, 支持非阻塞读取,目前没有可用数据:

如果设置了 O_NONBLOCK,read() 将返回 -1 并将 errno 设置为 [EAGAIN]。

如果 O_NONBLOCK 被清除,read() 将阻塞调用线程,直到某些数据可用。

不用说我们从未尝试过,甚至没有想过为有问题的文件描述符设置O_NONBLOCK

【讨论】:

    猜你喜欢
    • 2014-11-17
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多