诸暨市建设局行业管理网站,百度网站内容,网站建设英文专业术语,免费货源在线永久mmap 
一种内存映射文件的方法 
mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上#xff0c;如果文件的大小不是所有页的大小之和#xff0c;最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。 头文件 sys/mman.h 函数原型 
v…mmap 
一种内存映射文件的方法 
mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上如果文件的大小不是所有页的大小之和最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。 头文件 sys/mman.h 函数原型 
void* mmap(void* start,[size_t](https://baike.baidu.com/item/size_t/8101179?fromModulelemma_inlink) length,int prot,int flags,int fd,off_t offset);
int [munmap](https://baike.baidu.com/item/munmap/4568227?fromModulelemma_inlink)(void* start,size_t length);映射条件 
mmap()必须以PAGE_SIZE为单位进行映射而内存也只能以页为单位进行映射若要映射非PAGE_SIZE整数倍的地址范围要先进行内存对齐强行以PAGE_SIZE的倍数大小进行映射。 
mmap基础概念 
mmap是一种内存映射的方法这一功能可以用在文件的处理上即将一个文件或者其它对象映射到进程的地址空间实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。在编程时可以使某个磁盘文件的内容看起来像是内存中的一个数组。如果文件由记录组成而这些记录又能够用结构体来描述的话可以通过访问结构数组来更新文件的内容。 
内存映射原理 
mmap是一种内存映射文件的方法它将一个文件映射到进程的地址空间中实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。 
当磁盘地址和进程虚拟地址建立关系后进程就可以采用指针的方式读写操作这一段内存而系统会自动回写数据到磁盘上即直接完成了对文件的操作而不必在调用read/write等系统调用函数。同样的如果磁盘中内容有修改也会直接反映到用户空间其数据改变了。 
所以通过mmap映射方式可以使不同进程间共享磁盘文件其共享对象可为普通文件或匿名文件 
映射内存的分配 
mmap映射区域大小必须是物理页大小(page_size)的整倍数在Linux中内存页通常是4k。因为内存的最小粒度是页而进程虚拟地址空间和内存的映射也是以页为单位。为了匹配内存的操作mmap从磁盘到虚拟地址空间的映射也必须是页。 例如有一个文件的大小是5Kmmap函数从文件的起始位置映射5K到虚拟内存中由于内存物理页是4K虽然映射的文件只有5K但是实际上映射到内存区域的内存是8K以便满足物理页大小的整数倍。映射后对5~8K的内存区域用零填充对这部分的操作不会报错也不会写入到原文件中。 传统I/O读写流程 
用户进程发起文件数据的读请求内核通过查找进程文件符表定位内核已打开文件集上的文件信息从而找到文件inodeinode在address_space上查找要请求的文件页是否已缓存在页缓存中如已在缓存页中则直接返回这片文件页上的内容如不在缓存页上就会引发缺页中断。 当发生缺页中断时内核则调用nopage函数把所缺的页从磁盘装入到内存内核中及Page Cache中。接着再发起读页面过程从而将数据从页缓存中拷贝到用户空间中 特点 
常规文件操作为了读写效率和保护磁盘使用了页缓存机制 页缓存处在内核空间中不能直接被用户进程直接寻址需要将数据从页缓存中拷贝到主内存 
mmap读写流程 
用户进程调用进程内存映射函数库mmap当前进程在线程虚拟地址空间中寻找一段空闲的满足要求的虚拟地址。 
在当前进程的虚拟地址空间中寻找一段满足要求的虚拟地址为此虚拟地址分配一个虚拟内存区域vm_area_struct结构初始化该虚拟内存区域插入该虚拟内存区域到进程的虚拟地址区域链表中 
内核同样收到请求后会调用内核的mmap函数实现地址映射关系配对即进程虚拟地址空间 文件磁盘地址 关系映射该映射与内核内存没有任何关联 
进程调用mmap函数内核同样会得到消息最终内核调用自身的系统调用函数mmap。(两mmap函数不一样)内核mmap函数通过虚拟文件系统定位到文件磁盘物理地址。通过remap_pfn_range()建立页表实现了文件地址和虚拟地址区域的映射关系。 
进程的读/写操作访问虚拟地址空间这一段地址如果读写操作该改变了虚拟地址空间内容则一段时间后系统会自动回写脏页面到对应的磁盘地址中即完成了写入文件的操作。 
修改的脏页面不会立即更新而是有延时可以通过msync()来强制同步。通过此法能将所写的内容立即保存到磁盘中 特点 
用户空间与内核空间磁盘块通过映射直接交互不在间接通过页缓存。文件读写操作跨过了页缓存数据拷贝次数减少为只需一次借助硬盘的大空间对于大规模数据的读写避免对页内存空间大小的依赖提高操作效率。 mmap数据读写的性能提升就在于对数据的读写拷贝次数mmap只需要一次系统调用一次拷贝后续操作不需要系统调用。并且访问的数据不需要在page cache和用户缓冲区之间拷贝。 mmap读写优势 
对文件的读取操作跨过了页缓存减少了数据的拷贝次数用内存读写取代I/O读写提高了文件读取效率。实现了用户空间和内核空间的高效交互方式。两空间的各自修改操作可以直接反映在映射的区域内从而被对方空间及时捕捉。提供进程间共享内存及相互通信的方式。不管是父子进程还是无亲缘关系的进程都可以将自身用户空间映射到同一个文件或匿名映射到同一片区域。从而通过各自对映射区域的改动达到进程间通信和进程间共享的目的。 如果进程A和进程B都映射了区域C当A第一次读取C时通过缺页从磁盘复制文件页到内存中但当B再读C的相同页面时虽然也会产生缺页异常但是不再需要从磁盘中复制文件过来而可直接使用已经保存在内存中的文件数据。 可用于实现高效的大规模数据传输。内存空间不足是制约大数据操作的一个方面解决方案往往是借助硬盘空间协助操作补充内存的不足。但是进一步会造成大量的文件I/O操作极大影响效率。但凡是需要用磁盘空间代替内存的时候mmap都可以发挥其功效。 
mmap的使用 
mmap的函数位于内核的sys/mman.h 头文件中与其相关的几个函数也列出如下 
// 用户进程调用    函数用于将文件映射到内存
void* mmap(void addr, size_t length, int prot, int flags, int fd, off_t offset);
// 函数用于取消映射进程在映射空间对共享内容的改变并不直接写回到磁盘文件中往往在调用munmap() 后才执行该操作。
int munmap(void *addr, size_t length);
// 函数用于实现磁盘文件内容与共享内存区中的内容一致即同步操作。
// 除了调用munmap取消映射我们也可以调用msync()实现磁盘上文件内容与内核内存的内容一致
int msync(void * addr, size_t len, int flags);
mmap的使用场景 
1.Linux进程的创建 Linux执行一个程序这个程序在磁盘上为了执行这个程序需要把程序加载到内存中这时也是采用的是mmap。你可以从/proc/pid/maps看到每个进程的mmap状态。 内存分配 
我们使用c库的malloc申请内存malloc的分配内存有两个系统调用一个brk另一个就是mmap。 mmap不仅可以映射文件也可以映射内存当mmap使用的flag是MAP_ANONYMOUS称为建立匿名映射此时会忽略参数fd不涉及文件而且映射区域无法和其他进程共享。匿名映射存储的数据就是在物理内存上不属于任何文件。malloc分配内存底层就是用mmap的匿名映射来操作的。 Binder进程间通信 了解进程间通信的人都知道Android使用的是Binder进行进程间通信它的效率高于Linux其他传统的进程间通信因为它只要一次拷贝而之所以只需要进行一次拷贝的原因就在于使用了mmap。 最后以上就是app深度优化需要学习的MMAP内存映射的原理解析以及使用方法跟多Android核心技术或是Android性能优化的学习可以点击《Android核心优化性能学习手册》。点击查看类目 mmap优缺点 
优点 
mmap 防止数据丢失提高读写效率精简数据以最少量的数据局量表示最多的信息减少数据大小增量新增避免每次数据新增时的全量写入mmap对文件的读写操作只需要对磁盘到用户主存的一次数据拷贝过程减少了数据的拷贝次数提高文件读写效率。mmap使用逻辑内存对磁盘文件进行映射操作内存就相当于操作文件不需要开启线程操作mmap的速度和操作内存的速度一样快。mmap提供一块随时写入的内存app只管往里写入数据由操作系统如内存不足。进程退出时负责将内存写回到文件。不必担心crash导致数据丢失。mmap的适用场景是大文件的频繁读写这样就可以节省很多IO的耗时。即使进程意外死亡, 也能够通过 Linux 内核的保护机制, 将进行了文件映射的内存数据刷入到文件中, 提升了数据写入的可靠性 
缺点 
因为mmap是按照页存储方式进行存储每页4096字节如果数据只有100字节则正页将有大大的浪费。写回文件的工作由系统负责但是并不是实时的是定期写回到磁盘的中间如果发生内核崩溃、断电等还是会丢失数据不过可以通过msync将数据同步回磁盘。