[英]mmap() after deleting the file
I was told, that mmap() might be in trouble, if someone deletes the original file.有人告诉我,如果有人删除原始文件, mmap() 可能会遇到麻烦。 I was wondering if that really happens.
我想知道这是否真的发生了。 So i created some little test-program.
所以我创建了一些小测试程序。 I am using linux.
我正在使用 linux。
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(int, char**)
{
char const * const fileName = "/tmp/demo-file.dat";
size_t size;
{
struct stat st;
stat(fileName, &st);
size = st.st_size;
}
int fd = open(fileName, O_RDWR);
if (fd == -1)
{
std::cout << "open() failed, errno = " << errno << ":" << strerror(errno) << std::endl;
return (-1);
}
else
{
std::cout << "open() done (ok)" << std::endl;
}
for (int i = 20; i > 0; --i)
{
std::cout << "file open()'ed, wait #" << i << " seconds before mmap()" << std::endl;
sleep(1);
}
void *data = mmap((void*)0L, size, PROT_READ, MAP_SHARED, fd, (off_t)0);
if (data == (void*)-1)
{
std::cout << "mmap() failed, errno = " << errno << ":" << strerror(errno) << std::endl;
}
else
{
std::cout << "mmap() done (ok)" << std::endl;
}
for (int i = 20; i > 0; --i)
{
std::cout << "going to close() socket in #" << i << " seconds" << std::endl;
sleep (1);
}
close(fd);
for (int i = 30; i > 0; --i)
{
std::cout << "going to umap() files in #" << i << " seconds (still accessing the data)" << std::endl;
for (unsigned int x = 0; x < size; ++x)
{
char cp = *(char*) (data + x);
(void) cp;
}
sleep(1);
}
munmap(data, size);
for (int i = 30; i > 0; --i)
{
std::cout << "going to terminate #" << i << " seconds" << std::endl;
sleep(1);
}
return 0;
}
Whenever i delete the file - after the open() operation - it doesn't have negative impact to then mmap().每当我删除文件时 - 在 open() 操作之后 - 它不会对 mmap() 产生负面影响。 I can still acess the data in the test program.
我仍然可以访问测试程序中的数据。 When i delete the file right after close(), but before mmap(), it works.
当我在 close() 之后但在 mmap() 之前删除文件时,它可以工作。 I can also still see the old file in the /proc/[pid]/fd/ area:
我还可以在 /proc/[pid]/fd/ 区域看到旧文件:
lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)
The rest of the program works.程序的其余部分有效。
Even when i delete the file after the close() it still succeeds to access the mmap() data.即使我在 close()之后删除文件,它仍然可以成功访问 mmap() 数据。 However in both cases, after the close() i cannot see the
但是在这两种情况下,在close() 之后我都看不到
lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)
anymore.了。 (btw: where is then noted, that this file "still exists somehow"?)
(顺便说一句:然后注意到,这个文件“仍然以某种方式存在”?)
So is it the opposite, that it is guaranteed, that mmap() will still be able to operate on the data, even if the file was manually deleted (in a shell or by some other process)?那么是否相反,可以保证 mmap() 仍然能够对数据进行操作,即使文件被手动删除(在 shell 中或由其他某个进程)?
Here's what's happening.这就是正在发生的事情。
The first thing to check is首先要检查的是
$ls -i /tmp/demo-file.dat
65 /tmp/demo-file.dat
Note the inode number of the file is 65.注意文件的 inode 号是 65。
On starting the program, here's what it has in its lsof
output (apart from other entries not relevant to the current discourse)在启动程序时,这是它在
lsof
输出中的内容(除了与当前讨论无关的其他条目)
a.out 29271 zoso 3u REG 0,21 5 65 /tmp/demo-file.dat
This is a result of the open()
that's been done.这是已完成的
open()
的结果。 Note that the inode number is the same as the other file.请注意,inode 编号与其他文件相同。 The
open()
has increased the ref count on the same inode. open()
增加了同一 inode 上的引用计数。 Also, note that REG
indicates a regular file.另外,请注意
REG
表示常规文件。
Now if the file is deleted (using rm
etc.), here's what the lsof
looks like现在,如果文件被删除(使用
rm
等),这就是lsof
样子
a.out 29271 zoso 3u REG 0,21 5 65 /tmp/demo-file.dat (deleted)
This is expected since the file that was opened has been deleted but the handle that to its inode still is open in the process.这是意料之中的,因为打开的文件已被删除,但其 inode 的句柄在此过程中仍处于打开状态。
Moving on to the mmap, and here's the lsof
output转到 mmap,这是
lsof
输出
a.out 29271 zoso DEL REG 0,21 65 /tmp/demo-file.dat
a.out 29271 zoso 3u REG 0,21 5 65 /tmp/demo-file.dat (deleted)
Now there's another new entry but note that this is of type DEL
which indicates (lifting from lsof man page):现在有另一个新条目,但请注意,这是
DEL
类型,表示(从lsof手册页中提取):
''DEL'' for a Linux map file that has been deleted;
''DEL'' 表示已删除的 Linux 地图文件;
Since lsof
can't stat the original file anymore, it puts this mapping as DEL
with no size of course, yet note that the inode number still remains the same ie 65.由于
lsof
无法再统计原始文件,因此它将此映射作为DEL
放置,当然没有大小,但请注意 inode 编号仍然保持不变,即 65。
Now after close()
has been called on the fd here's what lsof
shows现在在 fd 上调用
close()
之后,这是lsof
显示的内容
a.out 29271 zoso DEL REG 0,21 65 /tmp/demo-file.dat
Note that the (deleted)
entry is gone since that fd to a REG
file has been closed and now only the mmap'd memory remains.请注意,
(deleted)
条目已消失,因为REG
文件的 fd 已关闭,现在仅保留了 mmap 的内存。
After munmap()
this entry too is gone (no more references to /tmp/demo-file.dat
and finally the program ends.在
munmap()
这个条目也消失了(不再引用/tmp/demo-file.dat
,最后程序结束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.