Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 删除文件后的mmap()_C++ - Fatal编程技术网

C++ 删除文件后的mmap()

C++ 删除文件后的mmap(),c++,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 <unis

有人告诉我,如果有人删除原始文件,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;
}
程序的其余部分工作正常

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

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
输出中的内容(除了与当前论述无关的其他条目)

这是已完成的
open()
操作的结果。请注意,inode编号与另一个文件相同。
open()
增加了同一inode上的ref计数。另外,请注意,
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
,表示(从手册页提升):

已删除的Linux映射文件的“DEL”

由于
lsof
无法再统计原始文件,它将此映射设置为
DEL
,当然没有大小,但请注意inode编号仍然保持不变,即65

现在,在fd上调用
close()
后,下面是
lsof
显示的内容

a.out   29271 zoso  DEL    REG   0,21                65 /tmp/demo-file.dat
请注意,
(已删除)
条目已消失,因为
REG
文件的fd已关闭,现在只剩下mmap的内存


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

文件仍将有一个活动的索引节点。索引节点通过引用计数保持活动状态。打开的文件句柄是一个引用。打开文件时,进程将接收指向文件索引节点的描述符或文件流。删除该文件只会重新启动。)移动目录中的文件项。在关闭最后一个引用之前,索引节点不会返回到文件系统。目录中的文件名不是该文件。Unix不是Windows。我知道文件描述符,因此显示在/proc/[pid]/fd/…如何为mmap()建模此引用计数?
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)
a.out   29271 zoso  DEL    REG   0,21                65 /tmp/demo-file.dat