mmap 用mmap實現cp命令

2021-06-25 13:40:37 字數 3394 閱讀 5400

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到底是何許人也,這次...