mmap操作提供了一種機制,讓使用者程式直接訪問裝置記憶體,這種機制,相比較在使用者空間和核心空間互相拷貝資料,效率更高。在要求高效能的應用中比較常用。mmap對映記憶體必須是頁面大小的整數倍,面向流的裝置不能進行mmap,mmap的實現和硬體有關。
mmap()系統呼叫使得程序之間通過對映同乙個普通檔案實現共享記憶體。普通檔案被對映到程序位址空間後,程序可以像訪問普通記憶體一樣對檔案進行訪問,不必再呼叫read(),write()等操作。
注:實際上,mmap()系統呼叫並不是完全為了用於共享記憶體而設計的。它本身提供了不同於一般對普通檔案的訪問方式,程序可以像讀寫記憶體一樣對普通檔案的操作。而posix或system v的共享記憶體ipc則純粹用於共享目的,當然mmap()實現共享記憶體也是其主要應用之一。
條件:mmap()必須以page_size為單位進行對映,而記憶體也只能以頁為單位進行對映,若要對映非page_size整數倍的位址範圍,要先進行記憶體對齊,強行以page_size的倍數大小進行對映。
優勢:
處理大檔案(浪費空間很小),或者在檔案大小恰好被 page 大小整除(沒有空間浪費)時,mmap()的優勢就會非常顯著。
在介紹mmap和read/write之前,首先先要介紹一下基礎知識,其中包括磁碟,檔案系統,記憶體。
首先說一下檔案系統,linux檔案系統的三層結構想必大家多少都了解一些,每個程序中都有乙個使用者檔案描述符表,表項指向乙個全域性的檔案表中的某個表項,檔案表表項有乙個指向記憶體inode的指標,每個inode唯一標識乙個檔案。如果同時有多個程序開啟同一檔案,他們的使用者檔案描述符表項指向不同的檔案表項,但是這些檔案表項會指向同乙個inode。
此時又會引出另外乙個東東:page cache。核心會為每個檔案單獨維護乙個page cache,使用者程序對於檔案的大多數讀寫操作會直接作用到page cache上,核心會選擇在適當的時候將page cache中的內容寫到磁碟上(當然我們可以手工fsync控制回寫),這樣可以大大減少磁碟的訪問次數,從而提高效能。page cache是linux核心檔案訪問過程中很重要的資料結構,page cache中會儲存使用者程序訪問過得該檔案的內容,這些內容以頁為單位儲存在記憶體中,當使用者需要訪問檔案中的某個偏移量上的資料時,核心會以偏移量為索引,找到相應的記憶體頁,如果該頁沒有讀入記憶體,則需要訪問磁碟讀取資料。為了提高頁得查詢速度同時節省page cache資料結構占用的記憶體,linux核心使用樹來儲存page cache中的頁。
在了解了以上的基礎之後,我們就來比較一下mmap和read/write的區別,先說一下read/write系統呼叫,read/write系統呼叫會有以下的操作:
訪問檔案,這涉及到使用者態到核心態的轉換讀取硬碟檔案中的對應資料,核心會採用預讀的方式,比如我們需要訪問100位元組,核心實際會將按照4kb(記憶體頁的大小)儲存在page cache中
將read中需要的資料,從page cache中拷貝到使用者緩衝區中
整個過程還是比較艱辛的,基本上涉及到使用者核心態的切換,還有就是資料拷貝接下來繼續說mmap吧,mmap系統呼叫是將硬碟檔案對映到用記憶體中,說的底層一些是將page cache中的頁直接對映到使用者程序位址空間中,從而程序可以直接訪問自身位址空間的虛擬位址來訪問page cache中的頁,這樣會並未涉及page cache到使用者緩衝區之間的拷貝,mmap系統呼叫與read/write呼叫的區別在於:
mmap只需要一次系統呼叫,後續操作不需要系統呼叫
訪問的資料不需要在page cache和使用者緩衝區之間拷貝
從上所述,當頻繁對乙個檔案進行讀取操作時,mmap會比read高效一些。
最後再說一下page cache的話題,從上面所說我們從磁碟檔案中讀取的內容都會存在page cache中,但當我們關閉這個檔案時,page cache中內容會立馬釋放掉嗎?答案是否,磁碟的讀取速度比記憶體慢太多,如果能命中page cache可以顯著提公升效能,萬一後續又有對這個檔案的操作,系統就可以很快速的響應。當然,這些檔案內容也不是一直存在page cache中的,一般只要系統有空閒物理記憶體,核心都會拿來當快取使用,但當物理記憶體不夠用,記憶體會清理出部分page cache應急,這也就是告訴我們程式對於物理記憶體的使用能省則省,交給核心使用,作用很大。
還有就是普通的write呼叫只是將資料寫到page cache中,並將其標記為dirty就返回了,磁碟i/o通常不會立即執行,這樣做的好處是減少磁碟的回寫次數,提供吞吐率,不足就是機器一旦意外掛程式掉,page cache中的資料就會丟失。一般安全性比較高的程式會在每次write之後,呼叫fsync立即將page cache中的內容回寫到磁碟中。
read和readFully的區別!
給你看些 你就明白是怎麼回事了!其實內部有進行判斷,但是並沒有進行處理!而是直接丟擲了異常!一下是jdk 的源 public void readfully byte b,int off,int len,boolean copy throws ioexception off n len n 從這裡不難...
read和readFully的區別!
給你看些 你就明白是怎麼回事了!其實內部有進行判斷,但是並沒有進行處理!而是直接丟擲了異常!一下是jdk 的源 public void readfully byte b,int off,int len,boolean copy throws ioexception off n len n 從這裡不難...
read系統呼叫,mmap系統呼叫
read系統呼叫,mmap系統呼叫 2012 07 23 09 54 28 分類 linux 標籤 linux 檔案系統 虛擬記憶體 儲存系統 字型大小 訂閱 一般情況下,操作檔案既可以使用標準i o,也可直接使用系統呼叫。兩者有何區別呢?在輸入輸出中,直接使用底層的系統呼叫效率是非常低的,為什麼?...