簡體   English   中英

刪除文件后的 mmap()

[英]mmap() after deleting the file

有人告訴我,如果有人刪除原始文件, 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)

了。 (順便說一句:然后注意到,這個文件“仍然以某種方式存在”?)

那么是否相反,可以保證 mmap() 仍然能夠對數據進行操作,即使文件被手動刪除(在 shell 中或由其他某個進程)?

這就是正在發生的事情。

首先要檢查的是

$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'' 表示已刪除的 Linux 地圖文件;

由於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 ,最后程序結束。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM