分享系列 之 linux IO原理与几种零拷贝机制的实现
今天分享的是一篇《linux IO原理与几种零拷贝机制的实现》,承接上一篇分享系列末尾说的“几种零拷贝机制的实现”来了(其实刚好都是同一天内搜到的),刚好今天周末,就都整理下发上来吧。上连接:
《深入剖析Linux IO原理和几种零拷贝机制的实现》
知乎原link:https://zhuanlan.zhihu.com/p/83398714
掘金link(带目录比较好翻一点):https://juejin.im/post/5d84bd1f6fb9a06b2d780df7#heading-15
PS:掘金link中的图已体现了引用知乎link的迹象,并且google过
掘金link右侧目录展示图如下,可以看到比较用心的内容递进和编排,涵盖面也够广(大佬轻拍):
从这篇分享中,你应该学习到的知识(基本也就是如上目录中的内容):
(1)虚拟内存机制使得使用同一块物理内存被不同的用户进程共享变得透明而简单。
(2)内核空间、内核模块(内核进程)、内核态,以及 用户空间、用户进程、用户态 等概念。
(3)IO中断原理,DMA传输原理(它为什么能让CPU和IO并行)
(4)传统IO读写方式对应的系统调用过程和流程,及其上下文切换次数、CPU在内核态拷贝次数、DMA拷贝次数 等
(5)零拷贝的几种实现思路:用户态直接 I/O,减少数据拷贝次数,写时复制技术
(6)用户态直接IO(第一种思路)的操作方式和弊端(或者说局限的场景)
(7)第二种思路“减少数据拷贝次数”的几种实现:mmap+write、sendfile、sendfile+DMA gather copy、splice、写时复制、缓冲区共享。通常能记住前三种就好。“写时复制方式”对java程序员来说 CopyOnWriteList API 应该是它的实现,不过已经是属于API层面的“零拷贝”了,和“mmap+write方式”一样也没有达到“真正的零拷贝”级别,而“真正的零拷贝”java程序员能接触到的估计只有 sendfile+DMA gather copy(linux 2.4起支持)这一种了。splice 和 缓冲区共享技术目前我在java方面还没接触到,有大佬做过相关总结的可以分享下~
(8)通过上面了解了 linux 底层支持的几种零拷贝方式和实现后,下面对 java NIO 和 netty、RocketMQ、Kafka 等的零拷贝实现,可以简单了解下就好。毕竟底层基础决定上层建筑,底层固定了,上层实现跑不出这几种方式。比如文末简短的分析了 kafka 索引文件使用的是 mmap+write 方式,数据文件使用的是 sendfile 方式。不管用没用过 kafka,但应该都听说过 kafka 消息会写进硬盘文件中,而对文件使用 sendfile,合理。索引文件通常会加载进内存中,sendfile 方式不再适用,因此 kafka 索引文件使用 mmap+write 方式减少数据拷贝,也合理~
同时,仍需要你辩证的看这篇“好文”,例如看的时候你觉得“不舒服”的地方,都先记录下来。
当然,一些小问题不影响大的方面,它仍然是一篇让我收获非常更多的在“linux零拷贝机制的几种实现”方面写的比较好的文章~
最后再贴一篇讲 sendfile 在 java NIO 中如何应用的文章:
Zero-Copy&sendfile浅析:https://blog.csdn.net/jiangbo_hit/article/details/6146502