Linux mmap內存映射,文件空洞詳解


前言:爲什麼要使用mmap內存映射?

我們知道,CPU從 I/O設備 讀寫的速度非常慢,而從 內存 讀寫的速度非常快,如果對一個文件需要進行多次讀寫,那麼每一次都調用 I/O
讀寫操作時很不划算的,於是我們便將這個文件 映射 到內存中,這樣CPU就可以直接快速讀寫。
mmap內存映射是一種空間換時間的思想。

mmap內存映射

  • void* mmap(void* addr, size_t len, int proc, int flags, int fd, off_t offset)

參數說明:

  • addr
    映射內存的地址,一般設置爲NULL,表示系統自動選擇內存映射的地址;也可以自己定義內存映射的地址

  • len
    需要映射的文件的大小

  • proc
    對映射區域的保護措施
    PROT_READ 可讀
    PROT_WRITE 可寫
    PROT_EXEC 可執行
    PROT_NONE 不能進行存取

  • flags
    在內存中修改了文件之後是否將修改複製回源文件
    MAP_SHARED 映射內存修改後會複製回源文件, 也就是 共享內存 技術
    MAP_PRIVATE 映射內存修改後不會回到源文件, 類似於 寫時複製(copy on write) 技術

  • fd
    文件句柄(文件描述符)

  • offset
    文件偏移, 注意必須是分頁大小的整數倍

  • 返回值
    成功則返回內存映射的起始地址,需要進行(char*)轉換,並讓一個char指針指向內存
    失敗則返回-1,也需要進行(char
    )強制轉換


案例1:共享內存設計

修改file文件中第一個字母爲 ‘m’, 再查看源文件file

int test1()
{
    const char *filename = "file";
    int ret;
    int fd = open(filename, O_RDWR);
    ERROR_CHECK(fd, -1, "open");
    char *file;
    struct stat statinfo;
    ret = stat(filename, &statinfo);
    ERROR_CHECK(ret, -1, "stat");
    file = (char *)mmap(NULL, statinfo.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    ERROR_CHECK((void *)file, (void *)-1, "mmap");
    cout << file << endl;
    file[0] = 'm';
    cout << file << endl;
    ret = munmap(file, statinfo.st_size);
    ERROR_CHECK(ret, -1, "munmap");
    close(fd);
    return 0;
}

案例2:父子進程的進程間通信

int test2()
{
    int fd = open("file2", O_RDWR | O_CREAT, 0755);
    char *buff = (char*)mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    ERROR_CHECK(buff, (char*)-1, "mmap");
    if (fork() == 0)
    {
        sprintf(buff, "%s", "child message");
        exit(0);
    }
    sleep(1);
    cout << "message from child: " << buff << endl;
    exit(0);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章