linux IO模型 (IO多路复用的三种机制Select,Poll,Epoll)

  • BIO -> 普通NIO -> select NIO -> epoll 同步非阻塞多路复用
    linux内核优化的结果

linux内核没有实现异步IO

  • 同步:轮询socket和读取数据的线程都是用户线程
  • 非阻塞:线程轮询socket 没有数据的时候不会阻塞

BIO


每一个socket都需要一个线程去阻塞读取
recvfrom系统调用一直是阻塞的 一个线程处理一个socket

  • 问题:多个线程、线程切换

普通NIO

一个线程一次次的发起对socket的轮训,recvfrom调用没数据就返回,有数据就同步处理
yum install man man-pages
man 2 read 系统调用文档
linux 面向文件描述符 cd /proc/pid/fd

  • 问题:连接多的时候,需要一次次系统调用

select NIO

多路复用:一个线程管理多个socket 适合连接数比较多的情况

selectort.select() 内核中的系统调用,查询每个socket是否有数据事件到达,如果没有会一直阻塞,导致用户线程的阻塞

select 轮询每个socket的状态是在内核空间进行的,效率高,之前在用户空间发起
返回给用户空间的是所有的socket还是有数据的socket ??

  • 问题:1 需要遍历文件描述符 2 需要在用户空间和内核空间传递文件描述符

poll相对于select来讲,没有了最大连接数的限制

epoll

信号驱动IO?
就绪列表 / mmap
epoll 数据结构: 双向链表 / 红黑树
系统调用:epoll_create epoll_ctl epoll_wait

异步IO

linux内核没有实现 windows内核实现了

异步IO模型才是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个asynchronous+read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要关心实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。
也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作。
mmap系统调用

零拷贝

sendfile系统调用 / 消息队列kafka MQ接收网络存储的消息并保存也是零拷贝(网络 -> mmap内存映射 -> 磁盘)


零拷贝.png

处理IO -> 处理文件描述符
socket 文件描述符file 关系?

参考资料
reids 五种IO模型介绍
https://blog.csdn.net/weixin_44100455/article/details/88956574
https://zhuanlan.zhihu.com/p/63179839
https://www.jianshu.com/p/397449cadc9a

你可能感兴趣的:(linux IO模型 (IO多路复用的三种机制Select,Poll,Epoll))