Linux學習筆記(內存映射mmap)

內存映射
內存映射,簡而言之就是將用戶空間的一段內存區域映射到內核空間,映射成功後,用戶對這段內存區域的修改可以直接反映到內核空間,同樣,內核空間對這段區域的修改也直接反映用戶空間。那麼對於內核空間<---->用戶空間兩者之間需要大量數據傳輸等操作的話效率是非常高的。

因爲mmap系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程可以像訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。

在這裏插入圖片描述
映射需要包含頭文件 #include<sys/mman.h>

映射函數 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
接觸映射函數 int munmap(void *addr, size_t length);

參數代表的意義
第一個參數void *addr:指定被映射到進程地址空間的起始地址,一般指定爲NULL,表示讓內核自己選擇。
第二個參數size_t length:需要映射的大小(字節)。
第三個參數int prot:數據的訪問權限,一般PROT_READ|PROT_WRITE表示可讀寫。
第四個參數int flags:一般指定爲MAP_SHARED
第五個參數int fd:映射的文件描述符
第六個參數off_t offset:從文件的什麼位置開始映射,一般指定爲0。

下面我來寫一個映射的程序:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/mman.h>

void sys_err(char *s)
{
    perror(s);
    exit(1);
}

int main(int argc,char** argv)
{
	//判斷傳入的參數個數是否大於等於2
    if(argc < 2)
    {
        printf("usage: mmap1 filename\n");
        return 1;
    }

	//創建一個fd用來接收文件描述符,即第二個參數,也是要被操作的文件
    int fd;
    fd = open(argv[1],O_RDWR);//argv[1]就是第二個參數

    if(fd < 0)
    {
        sys_err("open");
    }

    //獲得文件長度
    off_t len;
    len = lseek(fd,0,SEEK_END);

	//將文件映射到當前進程,mem代表映射後內存的首地址
    void* mem = mem = mmap(NULL,len,PROT_WRITE,MAP_SHARED,fd,0);

    //#define MAP_FAILED ((void*)-1)
    if(mem == MAP_FAILED)
    {
        sys_err("mmap");
    }

	//關閉文件描述
    close(fd);
	
	//用映射後的地址輸出文件內容
    printf("%s\n",mem);
	
	//通過映射來修改文件
    *(char*)mem = 'N';
    *(char*)(mem + 1) = 'I';
    ((char*)mem)[2]='H';
     ((char*)mem)[3]='A';

	
	//解除映射
    if(-1 == munmap(mem,len))
    {
        sys_err("munmap");
    }

    return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

執行結果爲:
在這裏插入圖片描述
成功的通過映射對文件進行修改!

注意:
mmap並不分配空間, 只是將文件映射到調用進程的地址空間裏(但是會佔掉你的 virutal memory)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章