【发布时间】:2010-06-19 03:26:36
【问题描述】:
根据 read(2) 的手册页,它只在到达 EOF 时返回零。
但是,这似乎是不正确的,它有时可能会返回零,可能是因为文件还没有准备好被读取?在从磁盘读取文件之前,我应该调用 select() 来查看它是否准备好了?
请注意,nBytes 为:1,445,888
一些示例代码:
fd_set readFdSet;
timeval timeOutTv;
timeOutTv.tv_sec = 0;
timeOutTv.tv_usec = 0;
// Let's see if we'll block on the read.
FD_ZERO(&readFdSet);
FD_SET(fd, &readFdSet);
int selectReturn = ::select(fd + 1, &readFdSet, NULL, NULL, &timeOutTv);
if (selectReturn == 0) {
// There is still more to read.
return false; // But return early.
} else if (selectReturn < 0) {
clog << "Error: select failure: " << strerror(errno) << endl;
abort();
} else {
assert(FD_ISSET(fd, &readFdSet));
try {
const int bufferSizeAvailable = _bufferSize - _availableIn;
if (_availableIn) {
assert(_availableIn <= _bufferSize);
memmove(_buffer, _buffer + bufferSizeAvailable, _availableIn);
}
ssize_t got = ::read(fd, _buffer + _availableIn, bufferSizeAvailable);
clog << " available: " << bufferSizeAvailable << " availableIn: "
<< _availableIn << " bufferSize: " << _bufferSize << " got "
<< got << endl;
return got == 0;
} catch (Err &err) {
err.append("During load from file.");
throw;
}
}
输出读取(当它失败且没有数据读取时):
available: 1445888 availableIn: 0 bufferSize: 1445888 got: 0
这是在 centos4 32 位上作为使用 VMware Server 1.0.10 的虚拟机运行的。正在读取的文件系统是虚拟机本地的。主机是windows server 2008 32位。
uname -a 说:
Linux q-centos4x32 2.6.9-89.0.25.ELsmp #1 SMP Thu May 6 12:28:03 EDT 2010 i686 i686 i386 GNU/Linux
我注意到下面给出的链接http://opengroup.org/onlinepubs/007908775/xsh/read.html 指出:
The value returned may be less than nbyte if the number of bytes left in the file is less than nbyte, if the read() request was interrupted by a signal...
If a read() is interrupted by a signal before it reads any data, it will return -1 with errno set to [EINTR].
If a read() is interrupted by a signal after it has successfully read some data, it will return the number of bytes read.
所以,也许我收到了一个中断读取的信号,因此返回的值为零,因为错误或者它认为读取了零字节?
【问题讨论】:
-
我想不出为什么它不在 EOF 时会返回 0。你能提供一个具体的例子来说明什么时候发生这种情况吗?
-
它发生在大约五万分之一的相同尝试中。
-
@Dummy00001 我正在使用 select() 因为 fd 可能是管道,因此不可用。但是,在这种失败的情况下,我们是从磁盘读取的。我已经更新了最后的问题以提供更多详细信息。
-
如果您在将
nbytes传递为 0 时读取 sysfs 的节点。驱动程序可能会将 0 作为 0 并且在errno返回 0 时不返回任何内容。这让我绊倒了一个小时。 . 只需将足够大的nbytes传递给read。