所以,这是一个奇怪的案例,我有时会看到它,但无法找出原因。
我们有一个从常规文件中读取的 C 程序。还有其他进程写入同一文件。该应用程序基于这样一个事实,即写入在 Linux 中是原子的,写入大小高达 4096 字节。
该文件没有使用非阻塞标志打开,所以我的假设是读取会阻塞。
但有时在启动过程中,我们看到 errno
中设置了">资源暂时不可用"错误。并且通过读取返回的大小 != -1 但一些部分读取大小。
错误消息如下所示:
2018-08-07T06:40:52.991141Z,无效的邮件大小,log_s.bin,fd 670,资源暂时不可用,读取大小 285,预期大小 525
我的问题是:
-
为什么我们在阻止文件读取方面
EAGAIN
? -
为什么返回值不是 -1?
-
这仅在启动时的初始时间内发生。此后工作正常。有哪些边缘情况会让我们陷入这种情况?
为什么我们在阻止文件读取时再次获得 EAGAIN?
你不是(见下文(。
为什么返回值不是 -1 ?
因为操作没有失败。
仅当对read()
的调用失败时,errno
的值才带有合理的值。当且仅当返回-1
时,对read()
的调用失败。
来自 Linux 手册页的 read()
:
返回值
成功后,返回读取的字节数(零表示结束( 文件(,并且文件位置按此数字前进。 是的 如果此数字小于字节数,则不是错误 要求;
[...]
出错时,返回 -1,并正确设置
errno
。
read()
的常见模式是
char buffer[BUFFER_MAX];
char * p = buffer;
size_t to_read = ... /* not larger then BUFFER_MAX! */
while (to_read > 0)
{
ssize_t result = read(..., p, to_read);
if (-1 == result)
{
if (EAGAIN == errno || EWOULDBLOCK == errno)
{
continue;
}
if (EINTR == errno)
{
continue; /* or break depending on application design. */
}
perror("read() failed");
exit(EXIT_FAILURE);
}
else if (0 < result)
{
to_read -= (size_t) result;
p += (size_t) result;
}
else if (0 == result) /* end of file / connection shut down for reading */
{
break;
}
else
{
fprintf(stderr, "read() returned the unexpected value of %zd. You probably hit a (kernel) bug ... :-/n", result);
exit(EXIT_FAILURE);
}
}
If (0 < to_read)
{
fprintf(stderr, "Encountered early end of stream. %zu bytes not read.n", to_read);
}