mmap函数建立文件的内存映射后,删除文件,能正常读取内容吗?

cxz7531 2011-02-24 03:59:41
运行的结果是,能正常读写,但不清楚为什么!有两种可能:
1 内存映射对应一块硬盘空间,文件删除后,内容还在,所以能读取。但如果别的进程把这块空间占了,就危险了。
这样,总归有出错的可能性。
2 内存映射对应一块硬盘空间,只要映射不解除,即使文件删除,硬盘上的那块空间还处于保护状态,这样算是安全的。

比如
void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fildes, 0);
指针addr 没有释放之前,原来硬盘上的那块区域能被别的进程写入吗?纠结中。
...全文
1134 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
cxz7531 2011-03-04
  • 打赏
  • 举报
回复
仔细做了测试,结果是这样:
1 A进程以只读方式打开该文件,然后建立内存映射,显示文件内容
2 B进程以读写方式打开文件,也建立内存映射,修改其中的内容,用msyn写回硬盘
3 A进程再次显示文件内容,跟步骤1的现实结果不一样,是修改后的内容。

这说明,A进程虽然以只读方式打开,但该文件所占空间,并没有处于保护状态。
justkk 2011-02-26
  • 打赏
  • 举报
回复
如果要搞明白这个问题,需要深入了解内存映射的机制

在了解内存映射的机制之前,保险的做法:
在munmap()之前,不要close()文件,这样即使删除了硬盘上的文件,其内容也不会被删除。
cxz7531 2011-02-25
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 laojing123 的回复:]
你所谓的 “读写” 都是针对内存的,这里相当于把文件加载到了内存。
在linux下执行可执行程序时照样可以删掉这些文件。一个道理。
[/Quote]

问题是我的文件是一个很大的字典,有几十兆之多,只读不写。按照大侠们的解释,貌似用只读方式来建立映射,是可以不占用实际内存的。我的应用最终是在嵌入式上用的,都读取到内存是不可忍受的。
而且以后字典尺寸还会逐渐增大,当增大到几百兆的时候,即使在PC上也无法都加到内存。

内存映射是一种续存技术,如果都在内存开辟一块同样大小的区域就失去意义了。
井朝天 2011-02-25
  • 打赏
  • 举报
回复
你所谓的 “读写” 都是针对内存的,这里相当于把文件加载到了内存。
在linux下执行可执行程序时照样可以删掉这些文件。一个道理。
justkk 2011-02-25
  • 打赏
  • 举报
回复
怀疑内存映射机制隐式的打开了文件

可以试验一下:
先打印一下当前的fildes的值;
在mmap()内存映射之后,munmap()之前,再随便打开一个另外一个文件,记录此时的文件描述符的值,然后关闭;
在munmap()之后,再随便打开一个文件,记录此时的文件描述符的值;

对比一下两个值是否相等
cxz7531 2011-02-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 justkk 的回复:]
apue上一句话:as long as some process has the file open, its contents will not be deleted

删除文件时,只要有进程正打开着那个文件,其内容不会被删除
这时内核应该采用某种机制防止硬盘上的这块数据被其它进程使用

内存映射时,你是不是没有关闭那个文件描述符,试试关闭描述符,再删除,看看结果..
[/Quote]

经过测试,即使关闭文件描述符以后仍然可以访问。
但两种访问不一定相同,也许关闭文件描述符后硬盘上的这块数据已经不被保护,但仅仅是还没被别的进程写入,所以仍然可以读出正确的数据。
justkk 2011-02-24
  • 打赏
  • 举报
回复
从你的需求来看,内存映射与文件保护关系不大啊
你解密之后,删除之前 --如果这时有人读文件,盗用成功

你也可以这样,不用内存映射,直接分配一个局部变量,读入文件全部内容,然后删除文件。
与你的内存映射效果差不多吧..
justkk 2011-02-24
  • 打赏
  • 举报
回复
apue上一句话:as long as some process has the file open, its contents will not be deleted

删除文件时,只要有进程正打开着那个文件,其内容不会被删除
这时内核应该采用某种机制防止硬盘上的这块数据被其它进程使用

内存映射时,你是不是没有关闭那个文件描述符,试试关闭描述符,再删除,看看结果..
cxz7531 2011-02-24
  • 打赏
  • 举报
回复
我的需求是这样。
需要读取一个加密文件,解密后文件必须创建在一个文件路径下才能供下一步所用,但又担心被盗用。
所以我在解密后建立内存映射,然后立即删除文件,通过内存映射访问其内容,退出的时候解除映射。
此种方案是否可行?经测试没问题。但如果该块硬盘空间被别的应用写入,就完了。
cxz7531 2011-02-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 justkk 的回复:]
文件删除之后,并没有真正删除,直到所有访问这个文件的进程关闭对应的描述符为止
[/Quote]

首先建立内存映射
void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fildes, 0);
最后解除映射
munmap(addr , fSize);

在建映射以后、解除映射之前,如果文件被删除,对应的那块空间会不会别的应用程序占据,还是在munmap执行前,该空间处于保护状态,禁止写入?
Rain208 2011-02-24
  • 打赏
  • 举报
回复
在文件系统中每一个inode都有一个引用值, 所谓的删除并不是真正的从文件系统中删除,只是把引用值减一,知道最后一个使用文件的进程结束后,才真正的把这个文件删除。
justkk 2011-02-24
  • 打赏
  • 举报
回复
文件删除之后,并没有真正删除,直到所有访问这个文件的进程关闭对应的描述符为止

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧