删除文件后删除mmap()

时间:2017-03-22 19:48:13

标签: c++

有人告诉我,如果有人删除原始文件,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 / area:

中看到旧文件
lrwx------ 1 frank frank 64 Mär 22 20:28 3 -> /tmp/demo-file.dat (deleted)

该计划的其余部分有效。

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

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

了。 (顺便说一句:然后注意到,这个文件“仍以某种方式存在”?)

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

1 个答案:

答案 0 :(得分:0)

这里发生了什么。

首先要检查的是

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

请注意文件65的inode编号。

启动程序时,此处有lsof输出内容(除了与当前话语无关的其他条目)

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

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

现在,如果文件被删除(使用rm等),这里lsof看起来像什么

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

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

转到mmap,这里是lsof输出

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

现在还有另一个新条目,但请注意,此类型为DEL,表示(从lsof手册页提升):

  

&#39;&#39; DEL&#39;&#39;对于已删除的Linux映射文件;

由于lsof不能再对原始文件进行统计,因此它将此映射设置为DEL,当然没有大小,但请注意,inode编号仍然保持不变,65。< / p>

现在,在fd上调用了close()之后lsof显示的内容

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

请注意,(deleted)条目已经消失,因为fd到REG文件已经关闭,现在只剩下mmap&#39}内存。

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