46 記憶體對映的保護和同步

2021-08-28 18:06:22 字數 2661 閱讀 1091

mmap函式的prot引數可指定記憶體對映區的保護許可權,例如指定prot_read和prot_exec,在呼叫open開啟檔案就應該指定o_rdonly或者o_rdwr。如果指定了prot_write,開啟的檔案應該使用o_wronly或者o_rdwr。

因為有些硬體的架構實現有些不同,所以對於保護許可權還是有區別的:

1. 一般開啟檔案指定o_rdwr標記就已經滿足基本的使用了。

2. 如果prot引數只指定了prot_write,且open以o_wronly標記開啟檔案,記憶體對映的保護許可權和開啟檔案的許可權理論上是相容的,但是呼叫mmap卻會失敗,設定errno為eacces錯誤。因為一些硬體架構上prot_write隱含了prot_read,這意味著系統分頁可寫也可讀,但這與o_wronly標記實際上是不相容的(這與硬體架構有關係)。

例如下面這一段**:

//以o_wronly許可權開啟檔案

int fd = open("test.txt", o_wronly, 0644);

if (fd < 0)

//拓展檔案大小4096

lseek(fd , 4096, seek_set);

write(fd , "0" , 1);

//指向檔案開頭

lseek(fd , 0 , seek_set);

//建立共享對映區,指定prot_write許可權

addr =(char *)mmap(null , 4096 , prot_write , map_shared , fd , 0);

if (addr == map_failed)

}

程式執行結果:

3. 以o_rdonly標記開啟乙個檔案,mmap呼叫指定了map_private建立私有記憶體對映,因為map_private對映上的修改操作不會反映到開啟的檔案中,所以prot引數可以指定任意的組合許可權。

對於乙個map_shared對映來說,在map_shared對映上的修改操作會反映到開啟的檔案中,唯一與o_rdonly標記相容的記憶體保護許可權就是prot_read | prot_exec。

通常為確保對映區的資料寫入物理磁碟上的檔案中,在呼叫munmap解除對映前需要呼叫msync函式。前面我們沒有呼叫msync函式依然能在檔案中看到寫入的資料,這是因為核心會自動將map_shared對映區的內容同步到開啟的檔案中,但核心並不保證何時同步資料。

通過呼叫msync函式可以讓應用程式顯式的控制檔案與記憶體對映中的資料同步。

#include int msync(void *addr, size_t length, int flags);
返回值:成功返回0,失敗返回-1並設定errno

length:需要同步的資料大小

flags:設定同步資料的方式(ms_sync,ms_async,ms_invalidate)

ms_sync:以同步方式寫入資料,當資料更新完畢就會返回

ms_async:以非同步方式寫入資料,不會等到更新完畢才返回,而是呼叫之後就立即返回

ms_invalidate:如果共享對映區和開啟的檔案中資料不一致,那麼共享對映區的內容就會失效,然後使用共享對映區的其他程序從開啟的檔案中複製對應的內容。

記憶體對映主要分兩種:檔案對映和匿名對映。檔案對映已經講了,在對映過程中需要依賴乙個檔案,而匿名對映顧名思義就是建立匿名的對映區,不需要依賴檔案。

可通過mmap函式的引數flags來指定map_anonymous (或map_anon)建立乙個匿名對映,由於不需要依賴檔案,引數fd設定為-1,例如:

char *addr = mmap(null, 4, prot_read|prot_write, map_shared|map_anonymous, -1, 0);
一般在linux上當指定了map_anonymous之後,會自動忽略引數fd的值,但是在類unix上可能必須指定map_anonymous並設定fd為-1,為了確保程式的可移植性,推薦這樣做。

#include #include #include #include #include #include #include int main(void)

pid = fork();

//父程序寫,子程序讀

if(pid > 0)else if(pid == 0)

munmap(addr , 4096);

return 0;

}

需要注意的是,map_anonymous和map_anon這兩個巨集是linux作業系統特有的巨集,如果在類

unix系統中如無該巨集定義,為了確保程式的移植性,

可以開啟

/dev/zero裝置檔案返回的檔案描述符,然後建立匿名對映區,**如下:

//開啟裝置檔案

fd = open("/dev/zero", o_rdwr);

//建立記憶體對映區

addr = (char *)mmap(null , 4096 , prot_read|prot_write , mmap_shared , fd , 0);

cache和記憶體的對映方式

cache是一種高速緩衝儲存器,她的主要作用是提高cpu資料輸入的速率,調和cpu速度與記憶體儲存速度之間的巨大差異。通俗一點說就是cpu太快,記憶體速度相對比較慢,而cache的速度快,但是cache的 比較昂貴。人們想到乙個辦法就是利用小容量的cache在cpu和記憶體中間當橋梁,也就是說把cp...

共享記憶體對映和占用記憶體關係

demo測試 對映檔案1g 1 對映1次,1寫,進行memset操作,共享記憶體佔1g 2 對映2次,1寫,1讀,單執行緒 1 1寫,進行memset操作,讀無操作,共享記憶體佔1g 2 1寫,進行memset操作,讀某個指定位置字元 len 2或len 1位置 共享記憶體佔1g 3 1寫,進行me...

inux記憶體對映和共享記憶體理解和區別

可以看到記憶體對映中需要的乙個引數是int fd 檔案的識別符號 可見函式是通過fd將檔案內容對映到乙個記憶體空間,我需要建立另乙個對映來得到檔案內容並統計或修改,這時我建立這另乙個對映用的仍是mmap函式,它仍需要用到fd這個檔案標識,那我不等於又重新開啟檔案讀取檔案裡的資料 1.既然這樣那同對檔...