IO模型_

多路复用

目前支持I/O多路复用的系统调用有 select,pselect,poll,epoll,I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,pselect,poll,epoll本质上都是同步I/O

1. Linux 五种IO模型

io两阶段

  1. 数据准备
  2. 数据从内核复制到用户空间

io模型
3. io 同步阻塞,(买奶茶 -》 等待 -》 逛街)
4. nio 同步非阻塞,通过轮询(买奶茶 -》 逛街时不断轮询服务员是否做完)
5. 多路复用 select,poll,epoll,reactor(同步阻塞,服务端单个线程处理多个请求,买奶茶-》用户等待轮询大屏幕看是否做好)
线程一次 select 调用可以获取内核态中多个数据通道的数据状态。其中,select只负责等,recvfrom只负责拷贝,阻塞IO中可以对多个文件描述符进行阻塞监听,是一种非常高效的 I/O 模型。
在这里插入图片描述

  1. 信号驱动io(买奶茶-》逛街-》电话通知-》自己去拿)
    在这里插入图片描述
  2. aio,异步io(点外卖-》玩-》送到家)
    在这里插入图片描述

2.多路复用之select、poll、epoll

等待多个连接,能实现同时对多个IO端口进行监听
epoll原理
快速从内核中获取到等待处理的事件,这几个都是网络事件收集器的模型,select和poll是判断所有的链接,判断哪些链接有事件进来了,扫描了大量不活跃的链接,epoll通过两个数据结构,链表(存储准备好的事件)红黑树(存储网络连接channel的读写事件,未就绪的事件),从而提高效率
在这里插入图片描述

  1. select()
    本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理,扫描时是线性扫描,即采用轮询的方法,效率较低
    缺点:
    • 单个进程所打开的FD是有一定限制的;socket进行扫描时是线性扫描,效率低
    • 维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大
  2. poll
    • 与select类似,使用链表存储fd,没有最大连接数限制
    • 大量的fd的数组被整体复制于用户态和内核地址空间之间
  3. epoll
    • callback而不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数;
    • 没有最大并发连接的限制
    • epoll通过内核与用户空间共享内存减少复制次数

select

基本原理
select 函数监视的文件描述符(通道的就绪状态)分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。

3. nio

  1. java selector事件选择,单线程管理多个通道,Selector.open() 方法创建一个 Selector 对象
  2. Channel 可以被注册到 Selector 对象上,在注册时候,需要指定通道的那些操作,是 Selector 感兴趣的。
  3. Channel.register(Selector sel, int pos) 方法,将一个通道注册到一个选择器
  4. 选择键,就绪状态通过Selector 的 select() 方法完成(依次询问每个通道是否已经就绪,效率不高),一旦通道有操作的就绪状态达成,并且是 Selecor 感兴趣的操作,就会被 Selector 选中,放入选择键集合中。 selector.selectedKeys();包含有channel和selector的注册关系和感兴趣的操作,类似事件驱动的event,只是是主动查询而不是被动的驱动
    在这里插入图片描述
    使用方式:
    // 1. 获取 Selector 选择器
    Selector selector = Selector.open();

// 2. 获取通道
ServerSocketChannel socketChannel = ServerSocketChannel.open();

// 3. 设置为非阻塞
socketChannel.configureBlocking(false);

// 4. 绑定连接
socketChannel.bind(new InetSocketAddress(9999));

// 5. 将通道注册到选择器
socketChannel.register(selector, SelectionKey.OP_ACCEPT);

// 6调用 Selector 中的 select 方法(循环调用),监听通道是否是就绪状态

// 7调用 SelectKeys() 方法就能获取 就绪 channel 集合

// 8遍历就绪的 channel 集合,判断就绪事件类型,实现具体的业务操作

4. Reactor 模式

有Reactor监听网络连接请求,通过Acceptor(IO线程池),转发(轮训)给io线程,io线程通过select监听读写事件,转发给业务线程处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值