阿里二面:什么是mmap?
平时在面试中你肯定会经常碰见的问题就是:RocketMQ为什么快?Kafka为什么快?什么是mmap?
这一类的问题都逃不过的一个点就是零拷贝,虽然还有一些其他的原因,但是今天我们的话题主要就是零拷贝。
传统IO
在开始谈零拷贝之前,首先要对传统的IO方式有一个概念。
基于传统的IO方式,底层实际上通过调用read()和write()来实现。
通过read()把数据从硬盘读取到内核缓冲区,再复制到用户缓冲区;然后再通过write()写入到socket缓冲区,最后写入网卡设备。

整个过程发生了4次用户态和内核态的上下文切换和4次拷贝,具体流程如下:
- 用户进程通过
read()方法向操作系统发起调用,此时上下文从用户态转向内核态 - DMA控制器把数据从硬盘中拷贝到读缓冲区
 - CPU把读缓冲区数据拷贝到应用缓冲区,上下文从内核态转为用户态,
read()返回 - 用户进程通过
write()方法发起调用,上下文从用户态转为内核态 - CPU将应用缓冲区中数据拷贝到socket缓冲区
 - DMA控制器把数据从socket缓冲区拷贝到网卡,上下文从内核态切换回用户态,
write()返回 

那么,这里指的用户态、内核态指的是什么?上下文切换又是什么?
简单来说,用户空间指的就是用户进程的运行空间,内核空间就是内核的运行空间。
如果进程运行在内核空间就是内核态,运行在用户空间就是用户态。
为了安全起见,他们之间是互相隔离的,而在用户态和内核态之间的上下文切换也是比较耗时的。
从上面我们可以看到,一次简单的IO过程产生了4次上下文切换,这个无疑在高并发场景下会对性能产生较大的影响。
那么什么又是DMA拷贝呢?
因为对于一个IO操作而言,都是通过CPU发出对应的指令来完成,但是相比CPU来说,IO的速度太慢了,CPU有大量的时间处于等待IO的状态。
因此就产生了DMA(Direct Memory Access)直接内存访问技术,本质上来说他就是一块主板上独立的芯片,通过它来进行内存和IO设备的数据传输,从而减少CPU的等待时间。
但是无论谁来拷贝,频繁的拷贝耗时也是对性能的影响。
零拷贝
零拷贝技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域,这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。
那么对于零拷贝而言,并非真的是完全没有数据拷贝的过程,只不过是减少用户态和内核态的切换次数以及CPU拷贝的次数。
这里,仅仅有针对性的来谈谈几种常见的零拷贝技术。
mmap+write
mmap+write简单来说就是使用mmap替换了read+write中的read操作,减少了一次CPU的拷贝。
mmap主要实现方式是将读缓冲区的地址和用户缓冲区的地址进行映射,内核缓冲区和应用缓冲区共享,从而减少了从读缓冲区到用户缓冲区的一次CPU拷贝。

整个过程发生了4次用户态和内核态的上下文切换和3次拷贝,具体流程如下:
- 用户进程通过
mmap()方法向操作系统发起调用,上下文从用户态转向内核态 - DMA控制器把数据从硬盘中拷贝到读缓冲区
 - 上下文从内核态转为用户态,mmap调用返回
 - 用户进程通过
write()方法发起调用,上下文从用户态转为内核态 - CPU将读缓冲区中数据拷贝到socket缓冲区
 - DMA控制器把数据从socket缓冲区拷贝到网卡,上下文从内核态切换回用户态,
write()返回 
mmap的方式节省了一次CPU拷贝,同时由于用户进程中的内存是虚拟的,只是映射到内核的读缓冲区,所以可以节省一半的内存空间,比较适合大文件的传输。
sendfile
相比mmap来说,sendfile同样减少了一次CPU拷贝,而且还减少了2次上下文切换。

sendfile是Linux2.1内核版本后引入的一个系统调用函数,通过使用sendfile数据可以直接在内核空间进行传输,因此避免了用户空间和内核空间的拷贝,同时由于使用sendfile替代了read+write从而节省了一次系统调用,也就是2次上下文切换。

整个过程发生了2次用户态和内核态的上下文切换和3次拷贝,具体流程如下:
- 用户进程通过
sendfile()方法向操作系统发起调用,上下文从用户态转向内核态 - DMA控制器把数据从硬盘中拷贝到读缓冲区
 - CPU将读缓冲区中数据拷贝到socket缓冲区
 - DMA控制器把数据从socket缓冲区拷贝到网卡,上下文从内核态切换回用户态,
sendfile调用返回 
sendfile方法IO数据对用户空间完全不可见,所以只能适用于完全不需要用户空间处理的情况,比如静态文件服务器。
sendfile+DMA Scatter/Gather
Linux2.4内核版本之后对sendfile做了进一步优化,通过引入新的硬件支持,这个方式叫做DMA Scatter/Gather 分散/收集功能。
它将读缓冲区中的数据描述信息--内存地址和偏移量记录到socket缓冲区,由 DMA 根据这些将数据从读缓冲区拷贝到网卡,相比之前版本减少了一次CPU拷贝的过程

整个过程发生了2次用户态和内核态的上下文切换和2次拷贝,其中更重要的是完全没有CPU拷贝,具体流程如下:
- 用户进程通过
sendfile()方法向操作系统发起调用,上下文从用户态转向内核态 - DMA控制器利用scatter把数据从硬盘中拷贝到读缓冲区离散存储
 - CPU把读缓冲区中的文件描述符和数据长度发送到socket缓冲区
 - DMA控制器根据文件描述符和数据长度,使用scatter/gather把数据从内核缓冲区拷贝到网卡
 sendfile()调用返回,上下文从内核态切换回用户态
DMA gather和sendfile一样数据对用户空间不可见,而且需要硬件支持,同时输入文件描述符只能是文件,但是过程中完全没有CPU拷贝过程,极大提升了性能。
应用场景
对于文章开头说的两个场景:RocketMQ和Kafka都使用到了零拷贝的技术。
对于MQ而言,无非就是生产者发送数据到MQ然后持久化到磁盘,之后消费者从MQ读取数据。
对于RocketMQ来说这两个步骤使用的是mmap+write,而Kafka则是使用mmap+write持久化数据,发送数据使用sendfile。
总结
由于CPU和IO速度的差异问题,产生了DMA技术,通过DMA搬运来减少CPU的等待时间。
传统的IOread+write方式会产生2次DMA拷贝+2次CPU拷贝,同时有4次上下文切换。
而通过mmap+write方式则产生2次DMA拷贝+1次CPU拷贝,4次上下文切换,通过内存映射减少了一次CPU拷贝,可以减少内存使用,适合大文件的传输。
sendfile方式是新增的一个系统调用函数,产生2次DMA拷贝+1次CPU拷贝,但是只有2次上下文切换。因为只有一次调用,减少了上下文的切换,但是用户空间对IO数据不可见,适用于静态文件服务器。
sendfile+DMA gather方式产生2次DMA拷贝,没有CPU拷贝,而且也只有2次上下文切换。虽然极大地提升了性能,但是需要依赖新的硬件设备支持。
参考:
https://juejin.cn/post/6844903949359644680#heading-19
https://www.cnblogs.com/xiaolincoding/p/13719610.html
https://time.geekbang.org/column/article/118657
https://www.toutiao.com/i6898240850917114380/
阿里二面:什么是mmap?的更多相关文章
- 阿里二面,面试官居然把 TCP 三次握手问的这么细致
		
TCP 的三次握手和四次挥手,可以说是老生常谈的经典问题了,通常也作为各大公司常见的面试考题,具有一定的水平区分度.看似是简单的面试问题,如果你的回答不符合面试官期待的水准,有可能就直接凉凉了. 本文 ...
 - 阿里2016实习offer五面经验与总结(转)
		
前言 目前楼主已经拿到阿里实习offer,一共经历了5次面试,其中4轮技术面,1轮HR面试.在这里分享一下自己的面试经验和学习总结.写这篇面经主要是希望能够帮助更多的小伙伴.我本科毕业于中南大学信管专 ...
 - 阿里Java研发工程师实习面经
		
十分幸运 拿到阿里云的offer,感谢周围无数人对我的支持和鼓励,所以写篇面经希望可以帮助大家. 面试中,运气占很大一部分的,所以你们若是没有通过,一定不要气馁,继续加油. 每个努力的人 都值得钦佩, ...
 - 阿里 & 酷家乐:实习生面试
		
最近海投了十家公司,暂时有阿里两面(已凉).酷家乐两面(大概凉了).网易一面.前两个都是基础知识发挥得还可以,两家公司二面都凉凉. 阿里一面(3.21 26min) 刚好买了中饭回宿舍打开正准备吃的时 ...
 - 秋招提前批小结(CVTE一面挂、阿里三面挂)
		
7月27日:CVTE一面 30分钟(挂) 1.自我介绍 2.有没有做过JavaWeb相关的项目?你觉得难点在哪里呢? 3.你这个博客系统有没有加权限系统?如果被拦截封包获取了账号密码怎么办?(没加,凉 ...
 - 阿里Java面经大全(整合版)
		
本文里的面经内容全部来源于牛客网,作为秋招备战复习与查缺补漏时使用.里面部分面经有我的注释和想法,以及部分解答,不一定正确,大家可以查询补充. 阿里巴巴,三面,java实习 昨天晚上11点打电话来,问 ...
 - 阿里Java研发工程师实习面经,附面试技巧
		
作者:如何进阿里 链接:https://www.nowcoder.com/discuss/72899?type=0&order=0&pos=17&page=1 来源:牛客网 前 ...
 - 阿里VS华为-开源镜像站体验及评测
		
最近对阿里和华为的开源镜像站做了深度体验,并将评测结果分享给大家: 一.评测产品: 华为开源镜像站(https://mirrors.huaweicloud.com/)以下简称 华为 阿里开源镜像站(h ...
 - 20届的阿里 头条 网易 滴滴 百度 小米等Java面经
		
转载连接 个人博客:junxuelian.cn 总结:个人感觉回答面试官问题不必太官方和书面化,腾讯sng招实习被发现照着百度百科念.结果可想而知.用自己的话和理解去回答就好.可能应届生会抱怨设计题, ...
 
随机推荐
- mybatis(一)常见ORM框架及JDBC操作工具类
			
转载:https://www.cnblogs.com/wuzhenzhao/p/11075569.html 在Java 程序里面去连接数据库,最原始的办法是使用JDBC 的API.我们先来回顾一下 ...
 - msfconsole web后门
			
一.PHP后门 在meterpreter中有一个名为PHP meterpreter的payload,利用这个可以成功反弹.步骤如下: 1. 使用msfvenom 创建一个webshell.php 2. ...
 - idle & js
			
idle & js idle meaning in js https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensi ...
 - Datahero Inc利用区块链溯源,造福各行各业
			
近些年来,随着区块链技术的不断崛起以及快速发展,越多越多的人提出将区块链技术引入到溯源系统当中,溯源也成为了区块链技术的重要应用场景之一. 目前,Datahero inc已建设一整套的溯源平台系统,基 ...
 - 2020 NGK 全球启动大会于美国硅谷圆满落幕
			
据NCC报道美国西海岸时间11月25日,NGK全球启动大会在美国加利福尼亚北部的硅谷会展中心成功举办.本次大会吸引了来自世界各地的企业家.创业者.开发者,以及投资人达一万人次齐聚硅谷. NGK创始人. ...
 - winform导入excel或者csv
			
if (txt01.Text != "") { this.lbzhantie.Items.Clear(); this.dtzhuanhuo.Rows.Clear(); if (tx ...
 - windows下的python环境安装
			
windows下python开发环境的搭建还是很方便的 python本体的下载可以通过官方渠道,也可以通过windows应用商店,这里推荐后者,因为前者还要设置环境变量,而且我设置了之后cmd下也没有 ...
 - SpringBoot以war包形式部署到外部Tomcat
			
SpringBoot 项目打包时能打成 .jar 与 .war包文件,.jar使用 java -jar xx.jar 就可以启动,而 .war 可以部署到tomcat的 webapps 中,随tomc ...
 - iOS中web与Js的交互
			
问题 感觉到uni-app框架有pit,公司强推该框架的小哥识趣的闭嘴,考虑到全盘替换周期跟成本挺大,基于uni-app能打包成H5,采用webview+js的原生方式集成 基本结构:原生壳 + we ...
 - 防数据泄露_MySQL库和数据安全
			
目录 攻击场景 外部入侵 内部盗取 防御体系建设 参考 在企业安全建设中有一个方向是防数据泄露,其中一块工作就是保障数据库安全,毕竟这里是数据的源头.当然数据库也分不同的种类,不同类型的数据库的防护手 ...