假设我们使用fopen()
打开了一个文件,并从收到的文件指针中获取文件描述符,使用fileno()
.然后我们做很多(>10^8)相对小块的随机read()
,大小在4字节到10KB之间:
errno
read()
如果文件系统是
-
ext3
-
NFS
-
OCFS2
-
2 和 3 的组合 (
OCFS2
通过NFS
)
?
我的读数给了我一个结论,1应该是不可能的。(如果文件尚未O_NONBLOCK
设置,如果可能的话,ext3
设置它)但对于其他三个(2.,3.,4.)我不确定。
(顺便说一句:我可以假设在任何情况下都没有将O_NONBLOCK
设置为默认值吗?
出现这个问题是因为我观察到read()
返回的字节少于请求的字节数,而没有在案例 4 中设置errno
。
通过测试深入研究这个问题的问题是,这种行为发生在<1/10000000000的情况下......-这仍然太频繁了:-}
更新:平均文件大小介于一些TBytes和大约1GB之间。
你不应该假设 read() 返回的字节数不会少于任何文件系统请求的字节数。 在大型读取的情况下尤其如此,因为 POSIX.1 指示大于 SSIZE_MAX 大小的 read() 行为取决于实现。 在我现在使用的这个主流Unix盒子上,SSIZE_MAX是32767字节。 read() 今天总是返回全部金额的事实并不意味着它将来会返回。
一个可能的原因可能是 I/O 优先级将来在内核中得到更充分的充实。 例如,您正在尝试从与另一个更高优先级进程相同的设备读取,并且如果您的进程不会导致磁头远离另一个进程想要的扇区,则另一个进程将获得更好的吞吐量。 内核可能会选择给你的 read() 一个简短的计数,让你暂时离开,而不是继续执行低效的交错块读取。 为了I/O效率,做了更奇怪的事情。 不被禁止的东西往往成为强制性的。
我们解决了描述的问题,即从位于NFS
挂载上的文件读取时read()
返回更少的字节,然后请求指向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
。