C语言 EAGAIN 在常规文件上的阻塞读取系统调用



所以,这是一个奇怪的案例,我有时会看到它,但无法找出原因。

我们有一个从常规文件中读取的 C 程序。还有其他进程写入同一文件。该应用程序基于这样一个事实,即写入在 Linux 中是原子的,写入大小高达 4096 字节。

该文件没有使用非阻塞标志打开,所以我的假设是读取会阻塞。

但有时在启动过程中,我们看到 errno 中设置了">资源暂时不可用"错误。并且通过读取返回的大小 != -1 但一些部分读取大小。

错误消息如下所示:

2018-08-07T06:40:52.991141Z,无效的邮件大小,log_s.bin,fd 670,资源暂时不可用,读取大小 285,预期大小 525

我的问题是:

  1. 为什么我们在阻止文件读取方面EAGAIN

  2. 为什么返回值不是 -1?

  3. 这仅在启动时的初始时间内发生。此后工作正常。有哪些边缘情况会让我们陷入这种情况?

为什么我们在阻止文件读取时再次获得 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);
}

最新更新