1,普通的read/write和mmap後的對映區域的讀寫到底有什麼區別。
2, 為什麼有時候會選擇mmap而放棄普通的read/write。
圍繞著這兩個問題分析一下,其實在考慮這些問題的同時不免和其他的很多系統機制產生互動。雖然是講解mmap,但是很多知識還是為了闡明問題做必要的鋪墊。這些知識也正是linux的繁瑣所在。乙個應用往往和系統中的多種機制互動。這篇文章中儘量減少對源**的引用和分析。把這樣的工作留到以後的細節分析中。但是很多分析的理論依據還是來自於源**。可見源**的重要地位。
基礎知識:
1, 程序每次切換後,都會在tlb base暫存器中重新load屬於每乙個程序自己的位址轉換基位址。在cpu當前執行的程序中都會有current巨集來表示當前的程序的資訊。應為這個**實現涉及到硬體架構的問題,為了避免差異的存在在文章中用到硬體知識的時候還是指明是x86的架構,畢竟x86的資料和分析的研究人員也比較多。其實arm還有其他類似的risc的晶元,只要有mmu支援的,都會有類似的基位址暫存器。
2, 在系統執行程序之前都會為每乙個程序分配屬於它自己的執行空間。並且這個空間的有效性依賴於tlb base中的內容。32位的系統中訪問的空間大小為4g。在這個空間中程序是「自由」的。所謂「自由」不是說對於4g的任何乙個位址或者一段空間都可以訪問。如果要訪問,還是要遵循位址有效性,就是tlb base中所指向的任何頁表轉換後的實體地址。其中的有效性有越界,許可權等等檢查。
3, 任何乙個使用者程序的執行在系統分配的空間中。這個空間可以有
vma:struct vm_area_struct來表示。所有的執行空間可以有這個結構體描述。使用者程序可以分為text data 段。這些段的具體在4g中的位置有不同的vma來描述。vma的管理又有其他機制保證,這些機制涉及到了演算法和物理記憶體管理等。請看一下兩個:
圖 一:
圖 二:
系統呼叫中的write和read:
這裡沒有指定確切的檔案系統型別作為分析的物件。找到系統呼叫號,然後確定具體的檔案系統所帶的file operation。在特定的file operation中有屬於每一種檔案系統自己的操作函式集合。其中就有read和write。
圖 三:
在真正的把使用者資料讀寫到磁碟或者是儲存裝置前,核心還會在page cache中管理這些資料。這些page的存在有效的管理了使用者資料和讀寫的效率。使用者資料不是直接來自於應用層,讀(read)或者是寫入(write)磁碟和儲存介質,而是被一層一層的應用所劃分,在每一層次中都會有不同的功能對應。最後發生互動時,在最恰當的時機觸發磁碟的操作。通過io驅動寫入磁碟和儲存介質。這裡主要強調page cache的管理。應為page的管理設計到了快取,這些快取以page的單位管理。在沒有io操作之前,暫時存放在系統空間中,而並未直接寫入磁碟或者存貯介質。
系統呼叫中的mmap:
當建立乙個或者切換乙個程序的同時,會把屬於這個當前程序的系統資訊載入。這些系統資訊中包含了當前程序的執行空間。當使用者程式呼叫mmap後。函式會在當前程序的空間中找到適合的vma來描述自己將要對映的區域。這個區域的作用就是將mmap函式中檔案描述符所指向的具體檔案中內容對映過來。
原理是:mmap的執行,僅僅是在核心中建立了檔案與虛擬記憶體空間的對應關係。使用者訪問這些虛擬記憶體空間時,頁面表裡面是沒有這些空間的表項的。當使用者程式試圖訪問這些對映的空間時,於是產生缺頁異常。核心捕捉這些異常,逐漸將檔案載入。所謂的載入過程,具體的操作就是read和write在管理pagecache。vma的結構體中有很檔案操作集。vma操作集中會有自己關於page cache的操作集合。這樣,雖然是兩種不同的系統呼叫,由於操作和呼叫觸發的路徑不同。但是最後還是落實到了page cache的管理。實現了檔案內容的操作。
ps:檔案的page cache管理也是很好的內容。涉及到了address space的操作。其中很多的內容和檔案操作相關。
效率對比:
mmap:
#include
#include
#include
#include
#include
#include
voidmain()
intfd = open("test.file", 0);
structstat statbuf;
char*start;
charbuf[2] = ;
intret = 0;
fstat(fd, &statbuf);
start = mmap(null, statbuf.st_size, prot_read, map_private, fd, 0);
dowhile(ret
read:
#include
#include
voidmain()
file*pf = fopen("test.file", "r");
charbuf[2] = ;
intret = 0;
dowhile(ret);
執行結果:
[xiangy@compiling-server test_read]$ time ./fread
real 0m0.901s
user 0m0.892s
sys 0m0.010s
[xiangy@compiling-server test_read]$ time ./mmap
real 0m0.112s
user 0m0.106s
sys 0m0.006s
[xiangy@compiling-server test_read]$ time ./read
real 0m15.549s
user 0m3.933s
sys 0m11.566s
[xiangy@compiling-server test_read]$ ll test.file
-rw-r--r-- 1 xiangy svx8004 23955531 sep 24 17:17 test.file
可以看出使用mmap後發現,系統呼叫所消耗的時間遠遠比普通的read少很多
Mmap的實現原理和應用
1,普通的read write和mmap後的對映區域的讀寫到底有什麼區別。2,為什麼有時候會選擇mmap而放棄普通的read write。圍繞著這兩個問題分析一下,其實在考慮這些問題的同時不免和其他的很多系統機制產生互動。雖然是講解mmap,但是很多知識還是為了闡明問題做必要的鋪墊。這些知識也正是l...
Mmap 實現原理和應用(流程)
在除錯完達文西的視屏輸入後記錄一下除錯心得。重點還是再次放在系統呼叫mmap後的記憶體分配上。做了乙個mmap系統呼叫的筆記以及記錄以備後用。大致介紹了linux中對於mmap的應用以及後續產生缺頁異常處理的乙個流程。由於之前的除錯中一直對於vma的區域選取產生疑問,不知道vma到底是何許人也,這次...
核心函式mmap的實現原理,機制
首先,檔案對映是虛存的中心概念,檔案對映一方面給使用者提供了一組措施,好似使用者將檔案對映到自己位址空間的某個部分,使用簡單的記憶體訪問指令讀寫檔案 另一方面,它也可以用於核心的基本組織模式,在這種模式種,核心將整個位址空間視為諸如檔案之類的一組不同物件的對映.中的傳統檔案訪問方式是,首先用open...