常见IO五种模型-阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO

简介: 用户空间与内核空间进程的寻址空间会划分为两部分:内核空间、用户空间用户空间只能执行受限的命令,而且不能直接调用系统资源,必须通过内核提供的接口来访问内核空间可以执行特权命令。调用一切系统资源

用户空间与内核空间


进程的寻址空间会划分为两部分:内核空间用户空间

用户空间只能执行受限的命令,而且不能直接调用系统资源,必须通过内核提供的接口来访问

内核空间可以执行特权命令。调用一切系统资源


阻塞IO


019f0f84ac15423d8961009537138dbd.png

在客户端连接数量不高的情况下,是没问题的。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量


非阻塞IO


7f28d4e3982a4ddca1108ad520db91ed.png

应用程序不断进行 I/O 系统调用轮询数据是否已经准备好的过程是十分消耗 CPU 资源的。


IO多路复用



如果调用recvform时,恰好没有数据,阻塞IO会使进程阻塞,非阻塞IO使CPU空转,不能充分发挥CPU作用

如果调用recvform时恰好有数据,则用户进程进入第二个阶段,读取并处理数据


文件描述符: 简称FD,是一个从0开始递增的无符号整数,用来关联Linux中的一个文件。在Linux中一切皆文件。

IO多路复用: 是利用单个线程来同时监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源

不同监听FD的方式、通知的方式有多种实现,常见的有:

select

poll

epoll

差异

select和poll只会通知进程有FD就绪,但不确定具体是那个FD,需要用户进程逐个遍历FD来确认

epoll则会通知用户进程FD就绪的同时,把已就绪的FD写入用户空间f7bb98ad6b574ee8b8fda12126532b4a.png


IO多路复用-selecte9e290fb506a48febe905729b32053e3.png

缺点

需要将整个fd_set从用户空间拷贝到内核空间,select结束还要再次拷贝回用户空间

select无法得知具体是那个fd就绪,需要遍历整个fd_set

fd_set监听的fd数量不能超过1024

IO多路复用-poll7ed80652660f4ec6994225ee57b00602.png

流程

创建pollfd数组,向其中添加关注fd信息,数组大小自定义

调用poll函数,将pollfd数组拷贝到内核空间,转链表存储,无上限

内核遍历fd,判断是否就绪

数据就绪或超时后,拷贝pollfd数组到用户空间,返回就绪fd数量

用户进程判断n是否大于0

大于0则遍历pollfd数组,找到就绪数组


与select对比

select模式中的fd_set大小固定为1024,而pollfd在内核中采用链表,理论上无上限

监听FD越多,每次遍历消耗时间也越久,性能反而会下降


IO多路复用-epoll7f80bb9e3f6341d3b09aa8fb4f47049e.png9206d0cd9a0b44d1b41beb0030a9537a.png

基于epoll实例中的红黑树保存要监听的FD,理论上无上限,而且增删改查效率都非常高,性能不会随着监听的FD数量增多而下降

每个FD只需执行一次epoll_ctl添加到红黑树,以后每次epol_wait无需传递任何参数,无需重复拷贝FD到内核空间

内核会将就绪的FD直接拷贝到用户空间的指定位置,用户进程无需遍历所有的FD就知道就绪的FD是谁


IO多路复用-事件通知机制

当FD有数据可读时,我们调用epoll_wait就可以得到通知,但是事件通知的模型有两种:

LevelTriggered:简称LT,当FD有数据可读时,会重复通知多次,直到数据处理完成

EdgeTriggered:简称ET,当FD有数据可读时,只会通知一次,不管数据是否处理完成


信号驱动IO


信号驱动IO是与内核建立SIGIO的信号关联并设置回调,当内核有FD就绪时,会发出SIGIO信号通知用户,期间用户应用可以执行其它业务,无需阻塞等待

0a77023eb35c4d8cb78e533402c4bc7a.png

当有大量IO操作时,信号较多,SIGIO处理函数不能及时处理可能导致信号队列溢出

而且内核空间与用户空间的频繁交互性能较低


异步IO


异步IO的整个过程都是非阻塞的,用户进程调用完异步API后就可以去做其它事情,内核等待数据就绪并拷贝到用户空间才会递交信号

d33e4630516745168739acdd679f13ad.png

相关文章
|
3月前
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
105 0
|
3月前
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
137 1
Linux C/C++之IO多路复用(aio)
|
3月前
|
并行计算 数据处理 Python
Python并发编程迷雾:IO密集型为何偏爱异步?CPU密集型又该如何应对?
在Python的并发编程世界中,没有万能的解决方案,只有最适合特定场景的方法。希望本文能够为你拨开迷雾,找到那条通往高效并发编程的光明大道。
51 2
|
4月前
|
开发框架 并行计算 算法
揭秘Python并发神器:IO密集型与CPU密集型任务的异步革命,你竟还傻傻分不清?
揭秘Python并发神器:IO密集型与CPU密集型任务的异步革命,你竟还傻傻分不清?
57 4
|
3月前
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
53 0
Linux C/C++之IO多路复用(poll,epoll)
|
3月前
|
Java Linux
【网络】高并发场景处理:线程池和IO多路复用
【网络】高并发场景处理:线程池和IO多路复用
77 2
|
3月前
|
监控 网络协议 Java
IO 多路复用? 什么是 IO 多路复用? 简单示例(日常生活)来解释 IO 多路复用 一看就懂! 大白话,可爱式(傻瓜式)教学! 保你懂!
本文通过日常生活中的简单示例解释了IO多路复用的概念,即一个线程通过监控多个socket来处理多个客户端请求,提高了效率,同时介绍了Linux系统中的select、poll和epoll三种IO多路复用的API。
200 2
|
5月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
6月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
4月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
268 12