MemoryMap

在涉及到IO的开发中,我们经常看到零拷贝(zero copy)、内存映射(memroy map, 以下简称mmap)等技术被用于提高IO效率,本文将介绍这两种技术的基本原理,说明它们是如何提高IO效率的。

相关概念

Zero copy和mmap涉及到操作系统中的一些基本概念,在了解它们的工作机制前,我们先来复习一下这些概念。

虚拟内存(virtual memory space)

进程对内存的读写不是直接使用物理内存地址,而是基于虚拟地址。

每个进程运行时,操作系统都会为其创建一个私有的虚拟内存,存放进程运行时代码和数据。虚拟内存大小取决与操作系统和所在机器的体系结构,对于32机器来说,空间大小为4g。

操作系统通过内存管理机制,将虚拟内存映射到物理内存。

虚拟内存使得操作系统可以同时支持多个运行进程安全共享物理内存,防止进程之间的不安全读写。

User space vs kernel space

虚拟内存分为两部分:用户空间和内核空间。用户空间存放用户代码和用户数据;内核空间存放操作系统代码。

前面说过,每个进程有自己私有的虚拟内存,不同进程的虚拟内存中的相同的地址,被映射到物理内存中的不同位置。但是内核空间是个例外,所有进程是共享内核空间的,也就是对不同进程来说,它们内核空间内的内容、地址映射实际上都是相同的。

缺页中断(page fault)

操作系统为每个进程的虚拟内存和物理内存之间建立了一张映射表,需要注意的是,虚拟内存中的内容只会一部分被装载到物理内存中。

当进程访问的虚拟地址对应的内容不在物理内存时,操作系统会触发一个缺页中断,将物理内存中不用的内容暂时置换到磁盘,将需要的内容读取道物理内存。通过这种管理模式,我们可以在同时运行多个进程的情况下,让每个进程觉得自己在独享整个内存空间。

User mode vs kernel mode

操作系统至少为进程提供两种运行模式:用户态(usermode)、内核态(kernel mode)。不同的模式,实际对应着不同的运行权限。

用户态的进程,只能访问用户空间,不能直接访问设备。而内核态的进程,可以访问用户空间和内核空间,可以访问硬件设备。

进程模式切换

一个进程可以通过系统调用在用户态和内核态之间切换,此外,中断、异常等机制也可以让进程冲用户态切换到内核态。

这里简单说明下系统调用的过程;

  1. 用户态进程准备好系统调用的参数;
  2. 进程执行trap指令
  3. cpu自动切换到内核态
  4. cpu读取进程事先设置的系统调用参数
  5. 执行指定的系统调用
  6. 结束后,进程重新被设置为用户态

工作过程分析

假定我们现在要实现一个读取文件,在内存中处理,然后将其输出的需求,我们看看在不同的实现方式中,底层究竟是如何工作的。

普通实现(read + write)

首先,我们使用常规的文件io操作实现需求。

普通IO
  1. 进程通过系统调用读取数据
  2. 进程切换到内核态,通知设备进行读取
  3. 设备准备好的数据传送到内核空间
  4. 接收到数据后,内核态进程将数据从内核空间拷贝到用户空间
  5. 进程切换回用户态,继续执行用户空间的代码:处理数据
  6. 进程通过系统调用输出数据到设备
  7. 进程切换到内核态,把数据从用户空间拷贝到内核空间,通知设备进行输出操作
  8. 设备完成任务后,进程再次从内核态切换回用户态

在上面的过程中,涉及到4次进程模式切换,两次内存拷贝。这些操作对性能会造成一定影响。

sendfile

接下来,我们通过sendfile调用,减少上述过程中的内存拷贝,实现零拷贝。

zero copy

通过sendfile,我们看到进程模式切换从4次减少到2次,拷贝从2次减少到1次。

但是sendfile只能完成文件的拷贝操作,无法处理文件内容,mmap则可以帮助我们实现零拷贝下的处理。

mmap

mmap

通过调用memory map,我们让操作系统把文件的内容映射到内存,对内存的读写将关联到对应的文件。而应用通过访问用户空间操作这部分内存,避免了内存拷贝操作。

对于内存映射,有些地方容易被误解,这里说明一下。

内存映射是文件到内存空间的映射

对于应用来说,和文件建立映射关系的是虚拟地址空间,而不是物理内存或者Heap。

当我们建立一个2g大小的映射时,并不是在heap,更不是在物理内存中分配了这么大的空间,仅仅是在虚拟地址空间中划出了这么大一个区域而已。

应用访问内存映射区域时,操作系统会把虚拟的地址映射成真正的物理内存地址和底层文件的偏移量。如果应用访问的虚拟地址对应的文件内容尚未被装入内存,操作系统通过缺页中断,将内存中的部分内容交换出去,腾出空间将文件的内容读取到内存。

内存映射对性能的提升是有条件的

通过内存映射访问文件,虽然减少了内存拷贝,减少了系统调用引起的进程模式切换,但是过程中需要承担缺页中断的负担。

对于小文件的读取,或者对于append模式的文件读写,内存映射的性能未必优于普通io操作。只有对大文件的随机访问,内存映射才可能有明显优势,不过这仍然需要更具体的分析和进一步的的benchmark测试。

Reference

User mode and Kernel mode, System calls, I/O, Exceptions

User space and kernel space

It's all about buffers: zero-copy, mmap and Java NIO

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容