Linux五种IO模型与非阻塞IO

1.五种IO模型

IO 分为读和写,所有 IO 操作统一包含两个核心步骤:等待 IO 事件就绪 + 数据拷贝。读 IO 与写 IO 整体流程框架一致,但数据流向和就绪判定条件不同。IO 模型共有五种,分别为:

  1. 阻塞 IO
  2. 非阻塞 IO
  3. 信号驱动 IO
  4. IO 多路复用(select/poll/epoll)
  5. 异步 IO

1.1同步通信 vs 异步通信

同步和异步关注的是消息通信与 IO 数据处理机制。所谓同步,就是在发出一个调用时,在没有得到最终结果之前,该调用不会返回;一旦调用返回,就已经拿到了结果。简言之:由调用者主动等待调用结果,主动参与数据拷贝过程。异步则相反,调用发出之后会立即直接返回,无需等待结果;后续由被调用者通过状态通知、信号或回调函数,主动把处理结果告知调用者,内核全权完成等待就绪和数据拷贝,无需进程参与。

另外,回忆多进程多线程中的同步和互斥,这里网络 IO 的同步异步通信,和进程线程间的同步制约,是完全不相干的概念。进程 / 线程同步:是进程、线程之间的直接制约关系。指为完成某一任务的多个线程,需要在关键位置协调执行次序、相互等待或传递信息产生的制约关系,常用于保护临界资源的安全访问。

后续看到 "同步" 一词,一定要先区分场景:是 IO 通信层面的同步,还是进程线程同步互斥层面的同步。

1.2阻塞 vs 非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息、返回值)时的线程状态。阻塞调用:调用结果返回前,当前线程会被挂起,让出 CPU,直到拿到结果后才返回继续执行。非阻塞调用:无法立刻获取结果时,调用也会立即返回,不会挂起当前线程,程序可以继续执行其他业务逻辑。

1.3非阻塞IO

非阻塞 IO 顾名思义,在 IO 事件没有就绪的时候不阻塞等待,而是立即返回,进程可以去处理其他事情。实现非阻塞可以使用 fcntl 函数,一个文件描述符默认是阻塞 IO,fcntl 函数原型为:int fcntl (int fd,int cmd,...);

fcntl 函数有 5 种功能:复制一个现有的描述符 (cmd=F_DUPFD)。获得 / 设置文件描述符标记 (cmd=F_GETFD 或 F_SETFD)。获得 / 设置文件状态标记 (cmd=F_GETFL 或 F_SETFL)。获得 / 设置异步 I/O 所有权 (cmd=F_GETOWN 或 F_SETOWN)。获得 / 设置记录锁 (cmd=F_GETLK,F_SETLK 或 F_SETLKW)。

设置文件描述符为非阻塞模式,需要使用 F_GETFL 和 F_SETFL 这两个命令组合完成,不能直接单独设置,核心步骤为先用 F_GETFL 获取原有文件状态标记,再通过按位或操作添加 O_NONBLOCK 非阻塞标记,最后用 F_SETFL 将新标记设置回去,保留原有属性不被覆盖。

cpp 复制代码
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

// 设置文件描述符fd为非阻塞模式
int set_nonblock(int fd)
{
    // 1. 获取文件原有的状态标记
    int old_flag = fcntl(fd, F_GETFL);
    if (old_flag == -1)
        return -1;

    // 2. 添加非阻塞标记,保留原有属性
    int new_flag = old_flag | O_NONBLOCK;

    // 3. 设置新的状态标记
    int ret = fcntl(fd, F_SETFL, new_flag);
    if (ret == -1)
        return -1;

    return 0;
}
相关推荐
ysa0510301 小时前
【板子】Dinic(最大网络流)
网络
我星期八休息1 小时前
网络编程—应用层HTTP协议
linux·运维·开发语言·前端·网络·网络协议·http
ShineWinsu2 小时前
对于Linux:UDPsocket编程基础的解析
linux·运维·网络协议·udp·ip·端口号·进程间通信
hehelm2 小时前
AI大模型接入SDK—通用模块设计
linux·开发语言·c++
ITxiaobing20232 小时前
IP库与AppsFlyer数据对账指南:破解国家/地区数据不一致的难题
网络·网络协议
有浔则灵2 小时前
GORM钩子函数详解
网络·安全·web安全
汇智信科4 小时前
图谱、向量、关键词、SQL多路一体,FastKG垂域召回率100%拉满
网络·数据库·ai编程·汇智信科·hsim·fastclaw·汇智龙虾
liulilittle4 小时前
论分布式系统的半开闭问题
服务器·网络·分布式·系统架构·竞态
FreeBuf_4 小时前
仅用六分钟,黑客借助Gemini CLI自主构建并迁移C&C僵尸网络
网络·人工智能
cyforkk4 小时前
Vercel 绑定自定义域名极简配置指南
服务器·前端·网络