来自文件的read() - 阻塞与非阻塞行为

时间:2012-04-16 17:20:17

标签: c linux nfs ocfs2

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

如果文件系统是

,那么read()的预期行为可能会返回更少的字节然后请求,而不设置errno
  1. ext3

  2. NFS

  3. OCFS2

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

  5. 我的阅读材料给了我一个结论,它不应该是1.(如果文件没有O_NONBLOCK设置,如果ext3可以设置它,那么对于其他三个( 2.,3.,4。)我不确定。

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

    出现这个问题是因为我观察到read()返回的字节数较少,然后在案例4中没有errno的情况下请求。

    通过测试来解决这个问题的问题是,这种行为发生在< 1/1000000000例...... - 这仍然太频繁了: - }

    更新:平均文件大小介于TBytes和1GByte之间。

2 个答案:

答案 0 :(得分:1)

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

一个可能的原因可能是未来内核中的I / O优先级更加充实。例如。您试图从同一设备读取另一个更高优先级的进程,如果您的进程没有导致磁头移动远离其他进程所需的扇区,则另一个进程将获得更好的吞吐量。内核可能会选择给你的read()一个简短的计数,让你暂时停止,而不是继续进行低效的交错块读取。为了I / O效率,Stranger things have been done。什么是不被禁止的通常是强制性的。

答案 1 :(得分:0)

我们解决了描述为read()返回较少字节的问题,然后从位于NFS mount上的文件读取请求,指向OCFS2文件系统(我的情况4)问题)。

事实上,使用上面提到的设置,文件描述符上的这样的read()有时会返回更少的字节然后请求,而不设置errno

要读取所有数据就像一次又一次read()一样简单,直到读取了所请求的数据量为止。

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

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

  

尝试读取文件(管道或FIFO除外)时   支持非阻塞读取,并且当前没有可用的数据:

     

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

     

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

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