读取为未缓存的直接I / O打开的文件的最后一个块不会产生EOF,正常行为?

时间:2014-06-11 08:01:01

标签: c winapi file-io io memory-alignment

我正在使用带有CreateFile()FILE_FLAG_NO_BUFFERING标记的FILE_FLAG_WRITE_THROUGH打开文件有几个原因,我注意到了一个奇怪的行为:

由于使用这些标志我们必须分配与扇区大小对齐的内存,假设扇区大小为512.

现在,如果我用_aligned_malloc()分配512个字节并且我从文件中读取,如果文件大小恰好是扇区大小的倍数,那么一切正常,比如512 * 4或2048.我读了512个字节的片段和最后一个片段使ReadFile()返回EOF代码,即返回FALSEGetLastError()设置为ERROR_HANDLE_EOF

当文件大小与扇区大小不对齐时,问题就出现了,也就是说,文件的大小是2048 + 13或2061字节。

我可以从文件中成功读取前4个512大小的块,并且对ReadFile()的第5个调用让我从文件中读取最新的13个剩余字节,但这是奇怪的事情:在这样的案例ReadFile()不会返回EOF代码!即使我告诉ReadFile()读取512个字节,并且它只读取13个字节(因此它超过了文件末尾),它也没有告诉我,并且只返回13个字节读取,而没有其他进一步的信息。

因此,当我读取最后13个字节并且我的循环设置为读取直到EOF时,它将再次调用ReadFile()第6次,导致错误:ERROR_INVALID_PARAMETER我猜这是是的,因为我在超过文件结尾后试图阅读!

我的问题是:这是正常行为还是我做错了什么?当使用非缓冲I / O时,我应该在读取最后一个非扇区对齐的文件块时没有EOF代码?或者有另一种方法可以做到这一点? 我怎么能理解我刚刚通过了EOF? 我想我可以通过修改循环来解决这个问题:直到EOF,我才能读取直到EOF OR ,直到实际返回的字节小于读取的请求字节。这是正确的假设吗?

注意:使用带有普通标志的文件时,不会发生,只有在我使用FILE_FLAG_NO_BUFFERINGFILE_FLAG_WRITE_THROUGH时才会发生。

注2:我正在使用I / O完成端口来读取文件,但我想这也是在不使用它们的情况下发生的,只需使用阻塞I / O.

1 个答案:

答案 0 :(得分:3)

EOF令人惊讶地难受。甚至C的feof功能也经常被误解。

基本上,你在第一种情况下得到ERROR_HANDLE_EOF来区分“512字节读取,更多读取”和“512字节读取,没有剩下”的情况。

在秒的情况下,这不是必需的。 “请求512个字节,读取13个字节,没有错误”已经意味着您已经处于EOF状态。部分阅读的任何其他原因都是错误的。