当前位置: 首页 > news >正文

Linux网络 五种 IO 模型

五种 IO 模型

在计算机网络和操作系统中,I/O(输入/输出)模型描述了程序如何与外部设备(如磁盘、网络接口等)进行数据交互,不同的I/O模型在处理I/O操作时的行为和性能表现各有不同。以下是五种常见的I/O模型及其特点。

阻塞I/O(Blocking I/O)

阻塞I/O是最简单的I/O模型。在这种模型中,当一个线程发起I/O操作时,它会被阻塞,直到I/O操作完成。线程在等待I/O操作完成期间无法执行其他任务。

在内核将数据准备好之前, 系统调用会一直等待, 所有的套接字 默认都是阻塞方式,下图以UDP为例。

  • 优点

    • 编程简单直观,易于理解和实现。

  • 缺点

    • 阻塞期间线程无法执行其他任务,资源利用率低。

    • 在高并发场景下,需要为每个连接创建一个线程,可能导致线程过多,增加系统开销。

非阻塞I/O(Non-blocking I/O)

非阻塞I/O允许线程在发起I/O操作时不被阻塞。如果数据尚未准备好,I/O操作会立即返回一个错误码(如 EAGAIN 或 EWOULDBLOCK)。通常需要在循环中不断轮询,直到数据准备好。

如果内核还未将数据准备好 , 系统调用仍然会直接返回, 并且返回错误码,下图以UDP为例。
  • 优点

    • 线程不会被阻塞,可以执行其他任务。

  • 缺点

    • 轮询机制可能导致CPU资源浪费,尤其是在数据未准备好时频繁轮询。

fcntl

在Linux中,可以通过 fcntl 系统调用将套接字设置为非阻塞模式。fcntl 用于修改文件描述符的属性,而套接字本质上也是一种文件描述符。

#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
  • fd:文件描述符,标识要操作的文件或对象。

  • cmd:指定要执行的命令,如下:

    • 复制一个现有的描述符(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)

  • arg:可选参数设置标志,具体含义取决于 cmd,这些标志包括:

    • O_RDONLY:只读模式

    • O_WRONLY:只写模式

    • O_RDWR:读写模式

    • O_NONBLOCK:非阻塞模式

    • O_APPEND:追加模式

fcntl 的返回值取决于执行的命令。如果操作成功,返回值通常是文件描述符或标志;如果失败,返回 -1 并设置 errno

实现应用

设置非阻塞套接字如下:

void SetNoBlock(int sockfd)
{
	int flag = fcntl(sockfd, F_GETFL);
	if (flag < 0)
	{
		perror("fcntl");
		return;
	}
	fcntl(sockfd, F_SETFL, flag | O_NONBLOCK);
}

信号驱动I/O(Signal-driven I/O)

信号驱动I/O模型允许线程在I/O操作准备好时接收信号通知。线程在等待I/O操作时不会被阻塞,而是通过信号处理函数来处理I/O事件。

线程使用 signal 或 sigaction 函数注册一个信号处理函数(如SIGIO),当I/O操作准备好时,系统则可以使用 kill 函数发送信号给线程,线程在信号处理函数中完成I/O操作,下图以UDP为例。

  • 优点

    • 线程不会被阻塞,可以继续执行其他任务。

    • 基于信号机制,响应速度快。

  • 缺点

    • 信号处理函数的执行时间需要严格控制,否则可能影响系统性能。

I/O多路复用(I/O Multiplexing)

I/O多路复用允许一个线程管理多个I/O操作。它通过系统调用(如select 、poll 、epoll)监控多个文件描述符,当其中一个文件描述符准备好时,系统调用返回。

线程调用select(),传入一组文件描述符。系统会阻塞线程,直到至少一个文件描述符准备好。线程可以同时处理多个I/O操作,而不需要为每个I/O操作创建一个线程,下图以UDP为例。

  • 优点

    • 高效利用线程资源,减少线程切换开销。

    • 适合高并发场景,可以同时管理大量连接。

  • 缺点

    • select 和 poll 的性能在大量文件描述符时可能下降,epoll 性能更好。

异步I/O(Asynchronous I/O)

异步I/O模型允许线程发起I/O操作后立即返回,由系统负责完成I/O操作,并在操作完成后通知线程。

线程调用异步I/O接口(如aio_read()、aio_write()),系统会异步执行I/O操作,并在操作完成后通过回调函数或信号通知线程。

  • 优点

    • 线程完全不参与I/O操作,资源利用率最高。

    • 适合高并发场景,可以显著提高系统吞吐量。

  • 缺点

    • 编程复杂度最高,需要处理异步回调逻辑。

    • 对系统支持要求较高,某些系统可能不完全支持异步I/O。

小结

任何 IO 过程中 , 都包含两个步骤 . 第一是 等待 , 第二是 拷贝 . 而且在实际的应用场景中, 等待消耗的时间往往都远远高于拷贝的时间 . IO 更高效 , 最核心的办法就是让等待的时间尽量少.

相关文章:

  • Netty基础—2.网络编程基础四
  • Linux运维(三)Linux命令行操作:从菜鸟到高手
  • 【性能测试】Jmeter如何做一份测试报告(3)
  • C++ 布尔类型(bool)深度解析
  • PHP+redis 优雅实现加锁机制
  • RedHatLinux的第一次作业
  • 单片机OTA升级中Bootloader怎么判断APP有没有问题?
  • java的字符串,数组,集合的长度/大小
  • 通用人工智能(AGI):定义、挑战与未来展望
  • 关于ngx-datatable no data empty message自定义模板解决方案
  • 在虚拟机VMware上安装CENTOS7-图文教程
  • 【iOS逆向与安全】sms短信转发插件与上传服务器开发
  • 解锁 Postman:下载安装与账户注册使用的全攻略,踏上测试新征程
  • 项目管理系统在制造企业 IPD 研发管理中的应用实践
  • 硬件电路 - 推挽(PP)输出与开漏(OD)输出的区别
  • ViM-UNet模型详解及代码复现
  • 如和实现一个服务器端高并发线程池
  • 【C++】滑动窗口算法
  • Kubernetes服务部署 —— Kafka
  • 安卓Android与iOS设备管理对比:企业选择指南
  • 东航C919航线上新!正式投入上海虹桥—深圳航线运营
  • 发射后失联,印度地球观测卫星发射任务宣告失败
  • 首次带人形机器人走科技节红毯,傅利叶顾捷:没太多包袱,很多事都能从零开始
  • 多地举办演唱会等吸引游客刺激消费,经济日报:引导粉丝经济理性健康发展
  • 沪指跌0.68%报3380.82点,创指跌1.92%:券商、军工跌幅靠前
  • 六连板成飞集成:航空零部件业务收入占比为1.74%,市场环境没有重大调整