Linux网络I/O复用并发模型
用户空间和内核空间
为了避免用户应用导致冲突甚至内核崩溃,用户应用与内核是分离的:
进程的寻址空间会划分为两部分:内核空间、用户空间。
用户空间只能执行受限的命令(Ring3),而且不能直接调用系统资源,必须通过内核提供的接口进行访问。
内核空间可以执行特权命令(Ring0),调用一切系统资源。

写数据:把用户缓冲区数据拷贝到内核缓冲区,然后写入设备。
读数据:从设备读取到内核缓冲区,再拷贝到用户缓冲区。

五种IO模型
几种IO网络模型的差异主要在:(1)等待数据就绪(2)数据拷贝
1.阻塞IO(Blocking IO)
用户进程在两个状态下都是阻塞的。阻塞等待,不占用CPU宝贵的时间片。

2.非阻塞IO(Nonblocking IO)
第一阶段不阻塞,第二阶段阻塞。非阻塞会让CPU空转,占用CPU系统资源。

3.IO多路复用(IO Multiplexing)
文件描述符(File Descriptor):简称FD,是一个从0开始递增的无符号整数,用来关联Linux中的一个文件,在Linux中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket)。
多路复用是利用单个线程来同时监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。

4.信号驱动IO(signal Driven IO)
与内核建立SIGIO的信号关联并设置回调,当内核有FD就绪时,会发出SIGIO信号通知用户,期间用户应用可以执行其它业务,无需阻塞等待。
缺点
(1)当有大量IO操作时,信号较多,SIGIO处理函数不能及时处理可能导致信号队列溢出
(2)内核空间与用户空间的频繁信号交互性能较低。

5.异步IO(Asynchronous IO)
整个过程都是非阻塞的,用户进程调用完异步API后就可以去做其他事情,内核等待数据就绪并拷贝到用户空间后才会递交信号,通知用户进程。用户进程在两个阶段都是非阻塞状态。
缺点:并发量很大的时候会创建太多FD;实现比较复杂。


实现I/O多路复用的几种机制
1.select

缺点:
需要将fd_set(图中黑框)从用户空间拷贝到内核空间,select结束还要再次拷贝回用户空间。
select无法得知具体是哪个fd就绪,需要遍历整个fd_set。
fd_set监听的fd数量不能超过1024,保存在位图里。
2.poll
IO流程:
(1)创建poolfd数组,向其中添加关注的fd信息,数组大小自定义
(2)调用poll函数,将pollfd数组拷贝到内核空间,转链表存储,无上限
(3)内核遍历fd,判断是否就绪
(4)数据就绪或超时后,拷贝pollfd数组到用户空间,返回就绪fd数量n
(5)数组进程判断n是否大于0
(6)大于0则遍历pollfd数组,找到就绪额fd
与select区别
select模式中fd_set大小固定1024,而pollfd在内核中采用链表,理论上无上限。
poll模式的缺点
需要遍历链表的所有FD,如果监听较多,性能会下降。
3.epoll


epoll模式中如何解决select和poll中的问题的?
基于epoll实例中的红黑树保存要监听的FD,理论上无上限,而且增删改查效率都非常高,性能不会随着监听的FD数量增多而下降。
每个FD只需要执行一次epoll_ctl添加到红黑树,以后每次epol_wait无需传任何参数,无需重复拷贝FD到内核空间。
内核会将就绪的FD直接拷贝到用户空间的指定位置,用户进程无需遍历所有FD就知道就绪的FD是谁。
事件通知机制
1.水平触发(level-triggered,LT)
当FD有数据可读时,会重复通知多次,直至数据处理完成,是Epoll的默认模式。
2.边缘触发(edge-triggered,ET)
当FD有数据可读时,只会被通知一次,不管数据是否处理完成。
惊群问题
当多个进程或线程同时监听同一个epoll实例时,如果有一个新的连接到来,内核会唤醒所有等待在该epoll实例上的进程或线程,但实际上只有一个进程或线程能成功处理该连接,其他被唤醒的进程或线程做了无效的操作,导致系统资源浪费和性能下降,在LT时会触发。
总结:select用int存fd,poll用链表,epoll用红黑树。
参考:
【黑马程序员Redis入门到实战教程,深度透析redis底层原理+redis分布式锁+企业解决方案+黑马点评实战项目】 https://www.bilibili.com/video/BV1cr4y1671t/?p=160&share_source=copy_web&vd_source=554f6cfaea00d504c732eb9b35cd6e8b
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)