gpt4 book ai didi

c++ - mmap() 删除文件后

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:44:00 25 4
gpt4 key购买 nike

有人告诉我,如果有人删除原始文件,mmap() 可能会有麻烦。我想知道这是否真的发生了。所以我创建了一些小测试程序。我正在使用 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;
}

每当我删除文件 - 在 open() 操作之后 - 它不会对 mmap() 产生负面影响。我仍然可以访问测试程序中的数据。当我在 close() 之后但在 mmap() 之前删除文件时,它起作用了。我还可以在/proc/[pid]/fd/区域中看到旧文件:

lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)

程序的其余部分工作正常。

即使我在 close() 之后 删除文件,它仍然可以成功访问 mmap() 数据。然而,在这两种情况下,之后 close() 我都看不到

lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)

不再。 (顺便说一句:然后在哪里指出,这个文件“仍然以某种方式存在”?)

那么是否相反,即使文件被手动删除(在 shell 中或通过其他进程),mmap() 仍然能够对数据进行操作?

最佳答案

这是正在发生的事情。

首先要检查的是

$ls -i /tmp/demo-file.dat
65 /tmp/demo-file.dat

注意文件的 inode 号是 65。

启动程序时,这是它在 lsof 输出中的内容(除了与当前话语不相关的其他条目)

a.out   29271 zoso    3u   REG   0,21        5       65 /tmp/demo-file.dat

这是已完成的 open() 的结果。请注意,inode 编号与其他文件相同。 open() 增加了同一 inode 上的引用计数。另请注意,REG 表示常规文件。

现在,如果文件被删除(使用 rm 等),这就是 lsof 的样子

a.out   29271 zoso    3u   REG   0,21        5       65 /tmp/demo-file.dat (deleted)

这是预料之中的,因为打开的文件已被删除,但其 inode 的句柄在此过程中仍处于打开状态。

继续进行 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)

现在有另一个新条目,但请注意,这是 DEL 类型,它指示(从 lsof 手册页中提取):

''DEL'' for a Linux map file that has been deleted;

因为 lsof 不能再统计原始文件,它把这个映射作为 DEL 当然没有大小,但请注意 inode 号仍然保持不变即 65。

现在在 fd 上调用 close() 后,lsof 显示

a.out   29271 zoso  DEL    REG   0,21                65 /tmp/demo-file.dat

请注意,(deleted) 条目已消失,因为对 REG 文件的 fd 已关闭,现在仅保留 mmap 的内存。

munmap() 之后,这个条目也消失了(不再引用 /tmp/demo-file.dat,最后程序结束。

关于c++ - mmap() 删除文件后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42961339/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com