如何理解Linux的IO模型

一、引言

1、什么是 Linux 的 IO 模型

Linux IO 模型是 Linux 操作系统中的 IO 处理机制,IO 就是数据在硬盘、内存、网卡等 IO 设备间移动的过程。

2、阅读本文的知识准备

(1)用户空间和内核空间

参见这篇文章 用户空间和内核空间

(2)file descriptor(文件描述符)

Linux 中一切皆文件,比如视频文件、可执行文件、键盘、显示器等等。Linux 为每个已打开的文件分配了一个编号,称为文件描述符,即文件唯一标识。

(3)阻塞与非阻塞说的是什么

阻塞与非阻塞关注的是应用程序调用 IO 后等待数据返回时的状态,简单说就是数据未就绪时是否等待。

阻塞指的是应用程序调用 IO 操作时,需要内核 IO 操作完成后才返回用户空间;非阻塞指的是应用程序调用 IO 操作后,内核立即返回一个值。

(4)同步与异步说的是什么

同步异步关注的是任务完成时的消息通知方式

同步指的是应用程序发起 IO 操作后,需要等待或轮询内核;异步指的是 IO 操作完成后,通知应用程序。

二、IO 模型种类

Blocking IO - 阻塞式 IO

以应用程序读取 socket 数据举例。

  1. 应用程序发起系统调用,读取 socket 数据,此时处于用户态
  2. 进入内核态,等待网卡数据到达,到达后复制网卡数据到内核空间,再从内核空间复制数据到用户空间;返回应用程序(在此期间应用程序一直处于阻塞状态)
  3. 此时处于用户态,应用程序处理数据。

从上述过程可以看出 Blocking IO 既是同步也是阻塞。期间经过了两次数据copy,经过了两次用户态/内核态切换。

阻塞式 IO 的优点就是简单易懂,缺点是进程/线程期间阻塞时间长,浪费资源,性能低下。
读取网络数据

注: read() 和 recvfrom() 的区别是,前者从文件系统读取数据,后者从 socket 接收数据。

Nonblocing IO - 非阻塞式 IO

以应用程序读取 socket 数据举例。

应用程序发起系统调用,读取 socket 数据,如果数据没有就绪,直接返回相应code,应用程序一直发起轮询,直到数据就绪。

非阻塞式 IO 的优点在于进程/线程发起 IO 操作时,如果数据没有就绪,不会阻塞。
缺点在于消耗 CPU 资源,至少多了一次系统调用,如果是本地文件读取的话可能还快点,对 socket 来说就会有大量空轮询,就比较鸡肋。
在这里插入图片描述

IO Multiplexing - IO 多路复用

IO 多路复用优化了非阻塞 IO 大量空轮询的问题。

底层实现有select、poll、epoll,不同操作系统支持的不同。以select举例:

  1. 应用程序发起系统调用,注册 fd 感兴趣的事件
  2. 内核发现有 fd 就绪,返回数量
  3. 程序轮询就绪的 fd_set
  4. 发起真正的 IO 操作

select 缺点: fd_set 有大小限制;需要轮询 fd,性能会有所下降。
poll fd_set 不受限制;
epoll 直接返回就绪的fd,不需要轮询。现在linux中的 tomcat、netty都有epoll实现。

从上述过程可以看出,IO 多路复用是同步非阻塞。
在这里插入图片描述

Signal-Driven IO - 信号驱动 IO

可以简单理解为一种异步回调,数据就绪时系统回调用户函数。

没用使用过,实际很少使用,具体缺点可以参考网上相关文章。

在这里插入图片描述

Asynchronous IO - 异步 IO

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值