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

如何在启用O_NONBLOCK的代码中捕获IO错误?

非阻塞IO(O_NONBLOCK)下的错误察觉与处理

当启用O_NONBLOCK标志调用非阻塞IO函数时,返回-1并不一定意味着发生了真实错误——这可能只是当前没有可用的IO资源(比如无数据可读、缓冲区已满)。要准确区分正常的非阻塞状态和真实IO错误,按以下步骤处理:

1. 先判断函数返回值

所有非阻塞IO函数(如read、write、connect、accept)的返回值是核心判断依据:

  • 返回值 ≥0:操作成功(对于read/write,返回值是处理的字节数;对于accept是新的fd;connect返回0表示成功)。
  • 返回值 = -1:需要进一步检查errno变量,区分临时状态和真实错误。

2. 读取errno区分情况

必须在函数返回-1后立即读取errno,因为后续的系统调用会覆盖这个变量的值。使用前要包含<errno.h>头文件。

临时非阻塞状态(非错误)

如果errno是EAGAIN或EWOULDBLOCK,说明当前IO操作无法立即完成,属于非阻塞模式下的正常情况:

  • 读操作:当前无数据可读,后续可通过select/poll/epoll等IO多路复用工具,等待fd变为可读后重试。
  • 写操作:输出缓冲区已满,等待fd变为可写后重试。
  • connect操作:若errno是EINPROGRESS,表示连接正在建立中,需后续通过select检查fd可写状态,再调用getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)确认连接是否成功。

真实IO错误

除上述值外的errno均为真实错误,常见错误码及处理方式:

  • EBADF:无效文件描述符,检查fd是否已关闭或未正确打开。
  • ECONNRESET:TCP连接被对方重置,需关闭当前fd并清理相关资源。
  • EINVAL:函数参数错误,检查调用时的参数合法性(比如缓冲区长度为0)。
  • EPIPE:管道破裂或TCP连接已关闭后尝试写操作,需关闭fd。

代码示例:非阻塞read的错误处理

#include <unistd.h>
#include <errno.h>
#include <stdio.h>

#define BUF_SIZE 1024

int handle_nonblock_read(int fd) {
    char buf[BUF_SIZE];
    ssize_t n = read(fd, buf, BUF_SIZE);
    
    if (n == -1) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            // 无数据,等待后重试
            printf("No data available, will wait for fd ready\n");
            return 0;
        } else {
            // 真实错误,输出信息并清理
            perror("read failed");
            close(fd);
            return -1;
        }
    } else if (n == 0) {
        // Socket场景下,说明对方关闭了连接
        printf("Peer closed connection\n");
        close(fd);
        return -1;
    } else {
        // 处理读取到的数据
        printf("Read %zd bytes: %.*s\n", n, (int)n, buf);
        return 0;
    }
}

注意事项

  • 不要对EAGAIN/EWOULDBLOCK调用perror,这会误导问题排查,因为它们不是错误。
  • 结合IO多路复用使用非阻塞IO时,先等待fd的可读/可写事件再执行操作,能减少临时状态的出现,同时也能及时捕获错误事件(比如fd出错时,select会标记为可读可写)。
  • 非阻塞connect不能直接用errno判断成功,必须通过getsockopt获取SO_ERROR来确认连接状态。

内容的提问来源于stack exchange,提问作者gitman-2021

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:20:40