IO常识简述【I/O模型&&零拷贝】

概要

用户发起IO读操作,一般就是两个动作,写操作就是逆向的动作

内核把网卡/磁盘的内容搬到内核空间(动作A),再把内核空间数据搬到用户空间(动作B)。

 

主要有五种模型

  • 同步阻塞

这个比较简单,就是用户发起操作后 静静的等待AB完成。完全block住

  • 同步非阻塞

这个其实和同步阻塞相差不大。动作B也是完全阻塞模式,动作A阶段 内核会直接告诉你没好,上面那个是没好不说 你等着。这个是轮训去问,别问 问就是没好。

  • 多路复用

这个也是阻塞的,好处是一个线程处理多个channel,数据到内核空间了, 通知用户线程去做读操作

类似一个代表,提大家等通知。boss workers

 

select

selector内部维护了一个数据结构(bitmap),存储已经接受的socket。复制一份交给内核去轮训对应的socket集合是否有期待的事件发生。如果发生了 就会置位(用户态到内核态的复制) 然后交给用户态完成事件的处理

epoll

epoll用红黑树存储socket对象,用一个list维护socket发生的事件,用户态只需要轮训该队列

 

区别

1.select和poll的fd是用户态创建,需要复制一份到内核态。内核态检测到fd事件到来 再回传到用户态,用户态进行遍历。

epoll是在内核态创建fd,有fd事件把这个拷贝到用户态

2.select和poll会遍历所有的fd的队列,epoll只会遍历有事件发生的fd对应队列

3.内核角度,fd数组在内核 都需要和硬件绑定 ,绑定很耗时。epoll的数组在内核中,绑定1次就好

 

  • 信号驱动

  • 异步

这个依赖操作系统了,就是发起后自己玩自己的,数据全部就绪 通知用户线程。

具体的是用户线程发read调用,注册一个回调函数

 

零拷贝技术

java-io的图

 

操作系统实现零拷贝主要有mmap和sendfile

mmap

将进程的地址空间和文件或者其他对象做一个映射,操作内存和操作磁盘效果一样,绕过了内核缓冲区

 

sendfile

sendfile系统调用在两个文件描述符之间直接传递数据(完全是内核中的操作),没有用户缓冲区和内核缓冲区拷贝的动作。

原理
sendfile() 系统调用利用 DMA 引擎将文件中的数据拷贝到操作系统内核缓冲区中,然后数据被拷贝到与 socket 相关的内核缓冲区中去。接下来,DMA 引擎将数据从内核 socket 缓冲区中拷贝到协议引擎中去。

sendfile() 系统调用不需要将数据拷贝或者映射到应用程序地址空间中去,所以 sendfile() 只是适用于应用程序地址空间不需要对所访问数据进行处理的情况。(局限性很大,java一般都是接受请求流 处理完返回出去)

简单归纳上述的过程:

sendfile系统调用利用DMA引擎将文件数据拷贝到内核缓冲区,之后数据被拷贝到内核socket缓冲区中
DMA引擎将数据从内核socket缓冲区拷贝到协议引擎中
网络数据 -> 内核缓冲区(叶缓存) -> 内核socket缓冲区 -> 协议引擎

实战应用:

kafka服务端在读取消息推送到客户端就是用的零拷贝技术,减少了内核态到用户态的文件复制和切换,pageCache直接到Socket缓冲区 大大提升了性能

 

参考资料

知乎大神关于java 直接内存的介绍 https://www.zhihu.com/question/57374068

mmap https://blog.csdn.net/qq_33611327/article/details/81738195

零拷贝 https://time.geekbang.org/column/article/232676?utm_campaign=guanwang&utm_source=baidu-ad&utm_medium=ppzq-pc&utm_content=title&utm_term=baidu-ad-ppzq-title

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值