当前位置: 技术问答>linux和unix
使用mmap的一点疑问
来源: 互联网 发布时间:2016-12-19
本文导语: 本人学艺不精,看书理解的 mmap系统调用应该是将文件映射到内存来,然后的读写应该是针对内存的吧,也就是说不会在实际文件上反映出来的,要通过调用msync系统调用才会回写。 不知道理解的对不对,但我测试了...
本人学艺不精,看书理解的 mmap系统调用应该是将文件映射到内存来,然后的读写应该是针对内存的吧,也就是说不会在实际文件上反映出来的,要通过调用msync系统调用才会回写。
不知道理解的对不对,但我测试了一下,大概流程如下:
fd = open();
p = mmap();
通过p直接写数据,没有调用munmap,也没有close(fd),直接按CTRL+C退出了,然后打开文件发现文件已经修改了,关机重启,文件内容依然是修改了的。
所以有点困惑,对mmap映射区域的写(修改)操作,到底是通过什么机制回写文件的,这个和调不调用munmap和close有关系吗?
还有如果是嵌入式系统,文件系统建立在FLASH上,又是怎么个情况?
不知道理解的对不对,但我测试了一下,大概流程如下:
fd = open();
p = mmap();
通过p直接写数据,没有调用munmap,也没有close(fd),直接按CTRL+C退出了,然后打开文件发现文件已经修改了,关机重启,文件内容依然是修改了的。
所以有点困惑,对mmap映射区域的写(修改)操作,到底是通过什么机制回写文件的,这个和调不调用munmap和close有关系吗?
还有如果是嵌入式系统,文件系统建立在FLASH上,又是怎么个情况?
|
这个不保证文件一定修改的
调用过msync后一般能保证。
如果你在一个I/O负载过重的系统上运行这个程序,系统是不保证把脏页立刻flush到文件中的。
最新的kernel不太了解,以前的kernel是系统维护2个队列,1个读队列,1个写队列。
你调用一个write,等于send 1个或多个写请求到这个写队列里,
最后kernel有几个kernel thread pdflush,(可能是page dirty flush的缩写),来取出写请求把实际的content写回到磁盘上。
调用过msync后一般能保证。
如果你在一个I/O负载过重的系统上运行这个程序,系统是不保证把脏页立刻flush到文件中的。
最新的kernel不太了解,以前的kernel是系统维护2个队列,1个读队列,1个写队列。
你调用一个write,等于send 1个或多个写请求到这个写队列里,
最后kernel有几个kernel thread pdflush,(可能是page dirty flush的缩写),来取出写请求把实际的content写回到磁盘上。
|
你调用mmap的flags参数是什么?
MAP_SHARED,写映射区就相当于写文件,文件不会立即更新,除非显式调用msync或munmap。
MAP_PRIVATE,创建一个私有的CopyOnWrite映射,写数据不会影响原文件。
mmap的时候只是建立映射,不会复制什么。写的时候会缺页,然后才真正分配内存。
MAP_SHARED,写映射区就相当于写文件,文件不会立即更新,除非显式调用msync或munmap。
MAP_PRIVATE,创建一个私有的CopyOnWrite映射,写数据不会影响原文件。
mmap的时候只是建立映射,不会复制什么。写的时候会缺页,然后才真正分配内存。
|
不知道楼主看的是不是apue,apue上程序清单14-12有类似程序,它就没有调用munmap,也没有close(fd),但是的确复制过去了。
仔细看书发现,在P393底部有一句话“对于MAP_SHARED区磁盘文件的更新,在写到存储映射区时按内核虚存算法自动进行”,这也就解释了为什么会结果正确。(我猜楼主的flags参数一定是MAP_SHARED吧!)
然后我又man mmap查看了一下man页,在MAP_SHARED区有这样一句话:
The file may not actually be updated until msync(2) or munmap() is called.
他用的词是may not,比较蛋疼。
总结:
1、经过楼主的实践证明,写文件的确是会自动进行的!
2、man告诉我们可能不会实时更新,所以这样不可靠!
3、所以应该显示调用msync和munmap函数,apue上的例子有点小问题。
最近在apue,与楼主共勉啊!
仔细看书发现,在P393底部有一句话“对于MAP_SHARED区磁盘文件的更新,在写到存储映射区时按内核虚存算法自动进行”,这也就解释了为什么会结果正确。(我猜楼主的flags参数一定是MAP_SHARED吧!)
然后我又man mmap查看了一下man页,在MAP_SHARED区有这样一句话:
The file may not actually be updated until msync(2) or munmap() is called.
他用的词是may not,比较蛋疼。
总结:
1、经过楼主的实践证明,写文件的确是会自动进行的!
2、man告诉我们可能不会实时更新,所以这样不可靠!
3、所以应该显示调用msync和munmap函数,apue上的例子有点小问题。
最近在apue,与楼主共勉啊!
|
参数为MAP_SHARED的话,内容的回写依赖于系统内部的内存换页机制,不能保证可以立刻回写到磁盘上。所以如果要保证一定写回磁盘,需要调用msync。
映射的时候应该是一次载入一部分内容,当需要读写后面内部的时候(当前载入的内容没有),会有缺页报告,然后再载入后面需要修改的内容,前面的如果有修改,就回写到磁盘上去。
映射的时候应该是一次载入一部分内容,当需要读写后面内部的时候(当前载入的内容没有),会有缺页报告,然后再载入后面需要修改的内容,前面的如果有修改,就回写到磁盘上去。