从文件读取() – 阻塞与非阻塞行为

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

预期行为这样一个read()可能会返回较less的字节,然后请求,没有设置errno ,如果文件系统是

  1. ext3

  2. NFS

  3. OCFS2

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

我的读书给了我的结论,它不应该是可能的1(如果文件没有设置O_NONBLOCK ,如果尽可能为ext3设置),但其他三个(2,3,4)米不确定。

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

出现这个问题是因为我观察到read()返回的字节数less于在case 4中没有errno请求的字节数。

通过testing进行深入研究的问题是,这种行为发生在<1/1000000000的情况下 – – 这仍然经常是: – }

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

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

一个可能的原因可能是未来在内核中I / O优先级更充分。 例如,如果您正在尝试从另一个更高优先级的进程读取相同的设备,而另一个进程将获得更好的吞吐量,如果您的进程不会导致头部远离其他进程想要的部分。 内核可能会选择给你的read()一小段时间,以避免一段时间,而不是继续做低效的交错块读取。 为了提高I / O效率, 已经做了一些奇怪的事情 。 什么是不被禁止的往往是强制性的。

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

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

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

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

我的结论是:通过NFS通过OCFS2 read()使得read()从文件中read()来自与read()规范不一致的套接字( read() http://pubs.opengroup.org/onlinepubs/9699919799/functions/read .html :

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

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

如果O_NONBLOCK清零,则read()应阻塞调用线程,直到某些数据可用。

不需要说我们从来没有尝试过,甚至没有想过为所讨论的文件描述符设置O_NONBLOCK