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;
}
相关推荐
爱吃香菜的初学者1 小时前
十四.Linux——消息队列
linux·运维·开发语言
Apipi*8 小时前
30天速通Linux 第六章信号及信号处理
linux·运维·信号处理
不像程序员的程序媛8 小时前
检测网络的命令mtr详解
网络
天启HTTP9 小时前
爬虫防封核心原理:IP轮换机制与风控规避逻辑
linux·服务器·网络·爬虫·tcp/ip
运维行者_9 小时前
网络性能监控怎么做?从自动发现到根因分析的4个环节
运维·服务器·网络·人工智能·支持向量机
hz5678911 小时前
涉密视频会议设备配置指南:终端、音视频采集与配套设施选型
服务器·网络·数据库·安全·实时音视频·信息与通信·智能硬件
广州浮点FLOATLIC11 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
优橙教育11 小时前
零基础学AI应用开发要多久?3个月能到什么水平
服务器·开发语言·网络·php
BLUcoding11 小时前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom
AIgorithmGEEK11 小时前
[Linux]从手写报头到内核套路:序列化、反序列化与自定义协议全链路
linux·运维·服务器·网络·序列化·反序列化