You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unix下如何获取fread、fgetc等函数的特定错误(如EAGAIN)?

如何在读取管道后获取特定错误(如EAGAIN)?

使用read系统调用读取非阻塞管道时,能正确获取EAGAIN错误(通过errno),但改用标准IO的fgetc函数时,仅返回EOF,errno被置为0,只能通过ferror得知发生了错误,无法获取具体的错误类型。

以下是测试代码及运行输出:

测试代码

#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

// 补充代码中缺失的buf定义
char buf[10];

int main() {
  int rw[2]; assert(!pipe(rw));
  int r = rw[0], w = rw[1];
  fcntl(r, F_SETFL, O_NONBLOCK);
  printf("This will return EAGAIN\n");
  printf(" read -> %i\n", read(r, buf, 10));
  printf(" errno = %i \"%s\" (EAGAIN=%i)\n", errno, strerror(errno), EAGAIN);

  errno = 0;
  FILE* f = fdopen(r, "r");
  printf(" fgetc -> %i (EOF=%i) errno=%i\n", fgetc(f), EOF, errno);
  printf(" ferror -> %i\n", ferror(f));
}

运行输出

This will return EAGAIN
 read -> -1
 errno = 11 "Resource temporarily unavailable" (EAGAIN=11)
 fgetc -> -1 (EOF=-1) errno=0
 ferror -> 1

解决方案

1. 直接使用系统调用替代标准IO函数

标准IO库(stdio)的设计目标是提供带缓冲的便捷IO操作,它会封装底层系统调用,并且不会总是保留底层的错误码信息,尤其在非阻塞IO场景下,标准IO函数的行为并不适配。

直接使用read、write等系统调用可以直接获取底层错误码(如EAGAIN),这是处理非阻塞管道IO最可靠的方式。

2. 避免在标准IO中使用非阻塞文件描述符

POSIX标准并未定义标准IO函数与非阻塞文件描述符配合的行为,不同系统的实现可能存在差异。如果一定要使用标准IO,建议将文件描述符设置为阻塞模式,否则无法保证能正确获取到具体的错误类型。

如果必须使用非阻塞模式且要结合标准IO,部分系统允许通过fileno(f)获取流对应的文件描述符,然后在ferror(f)为真时检查errno(需在调用标准IO函数前重置errno为0),但这种方式不具备跨平台兼容性,且依赖具体的stdio实现。


内容的提问来源于stack exchange,提问作者vitiral

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:43:27