文件映射IO(mmap - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 技术分享 >

文件映射IO(mmap

发表时间:2020-10-19

发布人:葵宇科技

浏览次数:29


本文介绍在POSIX情况应用文件映射IO操作的办法,文件映射IO又被称为存储映射IO,对于通俗文件而言,很多时刻它是高效的,它实际削减了数据的复制;同时它也可以用于特别的处所,用于过程之间的通信,共享内存的一种方法。


我们可以或许把一个文件想象成一块持续的数据,大年夜纯粹的数据角度来看,任何通俗文件都可以这么懂得。文件映射实际上是把文件的┞封块数据与我们法度榜样里的一块内存对应上了,应用我们操作这块内存的时刻,看上去现其实操作这个文件。这就是文件映射的概念。这个概念很巨大年夜,它直接避免了内核与用户之间的一层数据复制,所以很多时刻,它会比其它方法的文件操作更快一些,尤其对于通俗的磁盘文件而言更是如斯。


创建映射区:mmap
我们经由过程函数mmap来告诉操作体系把哪个文件映射哪块内存去,并且设置我们可能对这块内存的不克不及操作,就是对文件一样。
#include<sys/mman.h>
void* mmap(void* addr, size_t len, int port, int flag, int filedes, off_t off)
返回值:成功返回被映射的内存地址,掉败返回MAP_FIALED
参数 addr
这个只有在极少数情况下才不为0,这个参数告诉内核应用addr指定的值来竽暌钩射指定文件。当指定为0的时刻,告诉内核返回什么地址内其自身决定。除非异常懂得体系过程模式,或者对当前情况异常懂得,不然的话手工指定则个值老是弗采取。
参数 len
指定被映射的内存区域的长度。
参数 port
这个参数对应open函数的权限位,我们可以指定为:PROT_READ,映射区可读;PROT_WRITE,映射区可写;PROT_EXEC,映射区可履行;PROT_NONE,映射区弗查拜访。因为只能映射已经打开的文件,所以这个权限位不克不及超出open函数指定的权限,比如说袈溱open的时刻指定为只读,那就不克不及在此时指定PORT_WRITE。
参数 flag
这个参数指定了映射区的其它一些属性,权限的属性已经在port中指定。这里可能存在的典范值有:MAP_FIXED,针对addr属性,如不雅指定则个位,那么请求体系必须在指定的地址映射,这往往是弗采取的;MAP_SHARED,此标记解释指定映射区是共享的,意思就是说对内存的操作与对文件的操作是相对应的,它不克不及与MAP_PRIVATE标记一向应用,因为它们表达的意图是相反的;MAP_PRIVATE,该标记解释映射区是私用的,此时被映射的内存只能被当前里程应用,当进迟疑作的内存将会产生原文件的一个副本。

MAP_FIXED //应用指定的映射肇端地址,如不雅由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如不雅指定的肇端地址弗采取,操作将会掉败。并且肇端地址必须落在页的界线上。
MAP_SHARED //与其它所有映赡┞封个对象的过程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标记和以上标记是互斥的,只能应用个一一个。
MAP_DENYWRITE //这个标记被忽视。
MAP_EXECUTABLE //同上
MAP_NORESERVE //不要为这个映射保存交换空间。当交换空间被保存,对映射区修改的可能会获得包管。当交换空间不被保存,同时内存不足,对映射区的修改会引起段违例旌旗灯号。
MAP_LOCKED //锁定映射区的页面,大年夜而防止页面被交换出内存。
MAP_GROWSDOWN //用于客栈,告诉内核VM体系,映射区可以向下扩大。
MAP_ANONYMOUS //匿名映射,映射区不与任何文件接洽关系。
MAP_ANON //MAP_ANONYMOUS的别称,不再被应用。
MAP_FILE //兼容标记,被忽视。
MAP_32BIT //将映射区放在过程地址空间的低2GB,MAP_FIXED指准时会被忽视。当前这个标记只在x86-64平台上获得支撑。
MAP_POPULATE //为文件映射经由过程预读的方法预备好页表。随后对映射区的拜访不会被页违例壅塞。
MAP_NONBLOCK //仅和MAP_POPULATE一路应用时才有意义。不履行预读,只为已存在于内存中的页面建立页表人口。
    [img]http://img.blog.csdn.net/20150104160753744?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5keWh1YWJpbmc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center



fd:有效的文件描述词。一般是由open()函数返回,其值也可以设置为-1,此时须要指定flags参数中的MAP_ANON,注解进行的是匿名映射。
off_toffset:被映射对象内容的起点。


设置与同步映射区:mprotect、msync
在mmap中我们有很多选项来控制最后获得的映射区的一些属性,在调用mmap函数之后,我仍然可以对个中的一些属性进行调剂,这经由过程mprotect函数完成。此外在我们更新了内存的内容之后,这时可能想把这些内容同步稻磁逄中的文件,这经由过程msync函数来完成。
mprotect 函数可以更改一个已经存在的映射区的拜访权限。
#include<sys/mman.h>
int mprotect(void* addr, size_t len, int port)
返回值:成功返回0,掉败返回-1
参数 addr
这个参数是mmap返回的数值,此时它就是mprotect感化典范围。
参数 len
指定映射区的长度,它须要与mmap中指定雷同。
参数 port
在膳绫擎我们已经介绍了port的可能取值,mprotect功能就是把这个port指定的属性施加于响应的映射区上。
在映射区的内容更新了,内核并不是及时同步映射区与文件的,相反内核很少主动去同步,除非我们调用了函数msync或者封闭映射区(封闭映射区的时刻,也不是急速同步的)。
#include<sys/mman.h>
int msync(void* addr, size_t len, int flags)
返回:成功为0,掉败为-1
参数 addr与len
这两个参数完全等同于mprotect中的响应的参数。
参数 flags
我们可以经由过程指定flags为不合的值来请求内核进行的响应的同步操作:MS_ASYNC,这实际上不请求内核做什么,让内核自立去履行同步;MS_SYNC,请求内核在返回之前把写操作完成;MS_INVALIDATE,是一个可选的标记,它告诉内核丢弃没有同步的部分。


解除映射区:munmap
在过程寻出或者我们调用munmap的时刻,可以解除一个已经存在的映射区。而封闭映射区对应的文件是不会引起映射区的解除的。
#include<sys/mman.h>
int munmap(void* addr, size_t len)
返回:成功返回0,掉败返回-1
munmap的参数含义是明显而平常的,所以在这里不作描述,它们与之前的几个含义完全雷同。


留意:旌旗灯号、过程、页、文件
对映射区的操作可能引起两个旌旗灯号:SIGSEGV 与 SIGBUS。内核会在进查拜访了弗采取的内存时发送SIGSEGV旌旗灯号给过程,指导过程这一异常行动。比如对一个只读的映射区履行写操作将收到这一旌旗灯号。在映射的时刻,如不雅文件本身的大年夜小没有映射区的长度大年夜,那么在过程第一次拜访跨越文件大年夜小的内存区域的时刻,内核会发送旌旗灯号SIGBUS旌旗灯号,之后再次拜访此区域之前的处所都可以正常应用,但一旦再次跨越,两样也会收到旌旗灯号SIGBUS。所以一般情况都在映射之前调用诸如lseek+write如许的函数来改变文件现有大年夜小以合适映射区须要的长度。
过程调用fork一类函数的时刻子过程会复制父过程的地址空间,所以被映射的区域也会被映射,如斯映射区是父子过程共享的。可以经由过程这种方法实现父子过程的内存共享与通信。
大年夜内核的角度,内存是安页来治理的,所以在映射的时刻内核在指定大年夜小的基本上按页锷滔取整。页的大年夜小是体系相干的,在POSIX情况下可以经由过程调用sysconf函数来肯定。
只有在调用mmap时指定MAP_SHARED的情况文件内容才会真正改变,不然文件内容不会被同步,即使我们调用了msync或解除映射或过程终止。


相关案例查看更多