【I/O】Unix IO 介绍

IO 模型(一)

Unix IO

一个输入操作共包含两个阶段:

  • 等待数据准备好
  • 从内核将数据复制到进程

对于一个套接字上的输入操作,通常第一步是等待数据从网络中到达,当数据到达时,先将数据复制到内核缓冲区中,第二步就是将数据从内核缓冲区中复制到应用进程的缓冲区中

Unix IO 有五个模型:

  • 阻塞式 IO
  • 非阻塞式 IO
  • IO 多路复用(select 和 poll)
  • 信号驱动 IO
  • 异步 IO(AIO)

阻塞式 IO

阻塞式 IO 的阻塞说的是,在进行 IO 操作时,应用进程将会阻塞,直到数据被复制到进程缓冲区中才返回。

在阻塞式 IO 中,应用进程阻塞时并不意味着其他程序也被阻塞,其他的程序依旧可以运行,因此阻塞式 IO 在阻塞过程中不消耗 CPU 资源,这种模型的效率会比较高。

下面的代码中,recvfrom 用于接收 Socket 传来的数据,并复制到应用进程缓冲区。这里的 recvfrom 当做系统调用

c 复制代码
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

非阻塞式 IO

非阻塞式 IO 的非阻塞是,在进行 IO 操作时,应用进程不会阻塞,会系统调用定时轮询检查数据是否准备好,若没准备好内核会返回一个错误码,这种方式 CPU 会处理更多的系统调用,因此效率会比较低

IO 多路复用

使用 select 或是 poll 等待数据,并且可以等待多个套接字中任何一个变为可读,这个过程会进行阻塞,当某个套接字可读时返回,在使用 recvfrom 进行复制

IO 多路复用可以让单个进程有处理多个 IO 事件的能力,例如,一个 Web 服务器没有多路复用,每一个 Socket 连接都要创建一个线程去处理,如果同时有几万个连接,那么就需要创建相同数量的线程。

信号驱动 IO

应用进程使用 sigaction 进行系统调用,内核立即返回,应用进程可以继续执行,也就是说,在内核等待数据到达阶段应用进程是非阻塞的,可以继续执行。内核在数据到达后,会向应用进程发送 信号 ,应用进程在收到信号后,会在信号处理程序中调用 recvfrom 进行系统调用将数据复制到应用进程。

异步 IO

应用程序进行 aio_read 系统调用,立即返回,应用进程继续执行不会阻塞,内核在完成所有操作之后,向进程发送信号,异步 IO 的信号通知应用进程 IO 完成,而信号驱动 IO 的信号是通知应用进程可以开始 IO

同步 IO 与 异步 IO

  • 同步 IO:应用进程在调用 recvfrom 时会阻塞

  • 异步 IO:不会阻塞

阻塞式 IO、非阻塞式IO、IO多路复用、信号驱动 IO 都是同步 IO,虽然非阻塞式 I/O 和信号驱动 I/O 在等待数据阶段不会阻塞,但是在之后的将数据从内核复制到应用进程这个操作会阻塞。

相关推荐
期待のcode1 分钟前
Springboot数据层开发
java·spring boot·后端
未来coding6 分钟前
Spring AI ChatModel API 详解【基于官方文档】
java·后端·spring
无限进步_13 分钟前
C语言双向循环链表实现详解:哨兵位与循环结构
c语言·开发语言·数据结构·c++·后端·算法·链表
bcbnb19 分钟前
Charles抓包怎么用 Charles抓包工具详细教程、网络调试方法、HTTPS配置与手机抓包实战
后端
傲文博一25 分钟前
为什么我的产品尽量不用「外置」动态链接库
前端·后端
零日失眠者27 分钟前
【系统监控系列】005:CPU温度监控脚本
后端·python
踏浪无痕28 分钟前
Maven 依赖拉不下来?一文终结所有坑点
spring boot·后端·面试
踏浪无痕31 分钟前
你真的懂泛型吗?手写 MyBatis-Plus + Jackson,揭秘框架设计的精髓
后端·json·mybatis
随风飘的云33 分钟前
mysql的in查询列数据量非常大导致数据索引失效的解决方案
后端
凯哥197033 分钟前
离线使用 Docker 镜像
后端