在常规文件的阻止读取系统调用上进行EAGAIN

Aru*_*nmu 0 c linux posix input errno

因此,这是一个奇怪的案例,我有时会看到却无法找出原因。

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

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

但有时在启动过程中,我们会在中看到“ 资源暂时不可用 ”错误errno。读取的!= -1返回的大小,但部分读取的大小。

错误消息如下所示:

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

我的问题是:

  1. 为什么我们要EAGAIN阻止文件读取?

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

  3. 这仅在启动时的初始时间内发生。此后工作正常。在这种情况下,有哪些极端情况可以使我们陷入困境?

alk*_*alk 5

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

您不是(请参阅下文)。

为什么返回值不是-1?

因为操作没有失败。

如果对的调用失败,则的值errno 带有合理的值read()read()仅当-1返回时,对的调用失败。

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);
}
Run Code Online (Sandbox Code Playgroud)