mmap 可以把磁碟檔案的一部分直接對映到記憶體,這樣檔案中的位置直接就有對
應的記憶體位址,對檔案的讀寫可以直接用指標來做而不需要read/write 函式。
#include
void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);
int munmap(void *addr, size_t len);
引數:addr 一般為null,核心自動分配
len 對映區大小
prot 建立對映區的許可權
flag
map_shared 修改會更新到物理層上,即修改內容,物理磁碟也會跟著被修改
map_private 不會修改到物理層
filedes 檔案描述符等
off 偏移量的起始位置,以頁為單位
如果addr 引數為null,核心會自己在程序位址空間中選擇合適的位址建立映
射。如果addr 不是null,則給核心乙個提示,應該從什麼位址開始對映,內
核會選擇addr 之上的某個合適的位址開始對映。建立對映後,真正的對映首地
址通過返回值可以得到。len 引數是需要對映的那一部分檔案的長度。off 引數
是從檔案的什麼位置開始對映,必須是頁大小的整數倍(在32 位體系統結構上
通常是4k)。filedes 是代表該檔案的描述符。
prot 引數有四種取值:
• prot_exec 表示對映的這一段可執行,例如對映共享庫
• prot_read 表示對映的這一段可讀
• prot_write 表示對映的這一段可寫
• prot_none 表示對映的這一段不可訪問
flag 引數有很多種取值,這裡只講兩種,其它取值可檢視mmap(2)
• map_shared 多個程序對同乙個檔案的對映是共享的,乙個程序對對映的
記憶體做了修改,另乙個程序也會看到這種變化。
• map_private 多個程序對同乙個檔案的對映不是共享的,乙個程序對映
射的記憶體做了修改,另乙個程序並不會看到這種變化,也不會真的寫到
檔案中去。
如果mmap 成功則返回對映首位址,如果出錯則返回常數map_failed。當程序
終止時,該程序的對映記憶體會自動解除,也可以呼叫munmap 解除對映。munmap
成功返回0,出錯返回-1。
/*
*使用mmap,將乙個內容為「hello」的檔案內容,改為「abcdo」,不使用read/write做
*///建立乙個檔案,內容為hello
#include #include #include #include #include int main(void)
int len = lseek(fd, 0, seek_end);
printf("lseek:%d\n", len);
/* *null :讓核心自動制定對映區首位址
*len :制定對映區的大小
*prot_write:表示對映的這一段可寫
*map_shared:多程序共享,修改會更新到物理裝置上
*fd :要對映的檔案的描述符
*0 :從檔案的0號偏移位置開始對映
*/p = mmap(null, len, prot_write|prot_read, map_shared, fd, 0);
if(p == map_failed)
close(fd); //只要對映成功檔案即可關閉
// p[0] = 0x64636261;
strcpy(p, "abdco");
munmap(p, len); //解除對映
return 0;}/*
akaedu@akaedu-g41mt-d3:~/t74_system/0819_chp1_lseek_ctl_mmap_dup2$ ./mmap
lseek:6
*///開啟檔案,內容已修改為abcdo
/* *./mmap_cp src dst 使用mmap實現的命令列引數cp命令
*mmap的好處,把檔案當成陣列來看待,簡化程式邏輯,提高程式速度
*/#include #include #include #include #include #include int main(int argc, char *argv)
/* *對映區許可權必須小於等於檔案的許可權,建立對映區的過程隱含著一次檔案的
*讀操作,所以這裡應該是「讀寫」許可權,而不是「只寫」許可權
*使用o_wronly建立對映區會報錯
*/out = open(argv[2], o_rdwr|o_trunc|o_creat, 0644);
if(out == -1)
int len = lseek(in, 0, seek_end); //獲取檔案長度
/* *null :由核心指定對映區首位址
*len :對映區的大小
*prot_read :讀寫許可權為唯讀
*map_private:程序間不共享對映區,對映區被關閉後,
* 修改消失,不會更新到物理裝置上
*in :檔案描述符
*0 :對映檔案的偏移位置
*/s = (char *)mmap(null, len, prot_read, map_private, in, 0);
if(s == map_failed)
/* *由於對映區的大小不允許超過原始檔案的大小
*而目的檔案是使用o_creat|o_trunc建立的,所以建立對映區的時候
*目的檔案的大小是0個位元組,所以應該先拓展目的檔案的大小,
*然後在建立跟目的檔案對應的對映區, 如不拓展,將來在對對映區進行
*寫操作的時候就會出現「匯流排錯誤」
* *所以:建立目的對映區之前,應該先拓展目的檔案
*/lseek(out, len-1, seek_set);//不拓展,會出"匯流排錯誤"
//lseek只是修改記錄,並不真正拓展檔案,真正拓展是寫(io)操作做的。
write(out, "a", 1); //len-1 +'a'= len
//目的對映區許可權只寫,對映區選項是map_shared,才能更新到磁碟上
d = (char *)mmap(null, len, prot_write, map_shared, out, 0);
if(d == map_failed)
close(in);close(out); //對映區建立完畢,檔案即可關閉了。
memcpy(d, s, len);
#if 0
for(i = 0; i < len; i++)
*d++ = *s++;
#endif
return 0;
}
mmap實現共享記憶體
mmap概念 mmap將乙個檔案或者其它物件對映進記憶體。檔案被對映到多個頁上,如果檔案的大小不是所有頁的大小之和,最後乙個頁不被使用的空間將會清零。mmap在使用者空間對映呼叫系統中作用很大。mmap操作提供了一種機制,讓使用者程式直接訪問裝置記憶體,這種機制,相比較在使用者空間和核心空間互相拷貝...
使用mmap實現檔案的拷貝
mmap與munmap函式介紹 include include void mmap void start,size t length,int prot,int flag,int fd,off t offset 返回 若成功時則返回對映區域的指標,若出錯則為map failed 1 start 最好從...
Mmap 實現原理和應用(流程)
在除錯完達文西的視屏輸入後記錄一下除錯心得。重點還是再次放在系統呼叫mmap後的記憶體分配上。做了乙個mmap系統呼叫的筆記以及記錄以備後用。大致介紹了linux中對於mmap的應用以及後續產生缺頁異常處理的乙個流程。由於之前的除錯中一直對於vma的區域選取產生疑問,不知道vma到底是何許人也,這次...