EAGAIN对常规文件的阻塞读取系统调用

问题描述 投票:0回答:1

所以,这是一个奇怪的案例,我有时会看到并且无法弄清楚原因。

我们有一个从常规文件中读取的C程序。还有其他进程写入同一个文件。该应用程序基于以下事实:在Linux中写入是原子的,写入大小最多为4096字节。

该文件未使用非阻塞标志打开,因此我的假设是读取将被阻塞。

但有时在启动期间,我们会在errno中看到“资源暂时不可用”错误集。并且read!= -1返回的大小,但有一些部分读取大小。

错误消息看起来像:

 2018-08-07T06:40:52.991141Z, Invalid message size, log_s.bin, fd 670, Resource temporarily unavailable, read size 285, expected size 525

我的问题是:

  1. 为什么我们在阻止文件读取时获得EAGAIN
  2. 为什么返回值不是-1?
  3. 这仅在启动时的初始时间发生。之后它运作良好。有什么边缘案例可以让我们处于这种情况?
c linux input posix errno
1个回答
5
投票

为什么我们在阻止文件读取时获得EAGAIN?

你不是(见下文)。

为什么返回值不是-1?

因为操作没有失败。

如果对errno的调用失败,read()的值只有一个合理的值。当且仅当read()被退回时,对-1的调用失败。

来自Linux man-page for 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.