|
以下希望藉由一個實際可以在user mode運作的API, mmap()$ I" k2 j( w3 h8 O- S& e" l
讓programmer能夠感受到MMU這個硬體在系統中所扮演的角色/ u7 z, o. z, ]. x# Z/ D
: ^1 q+ a5 W9 ?0 S t1 {+ j0 L; J
寫linux底下driver的人常常會看到這個東西 mmap()
5 r1 G% W) ]1 ?3 ~% `: S在user mode program裡面假如你用open( "/dev/xxx", ... )
; \& u9 X5 B: y. y* I7 t3 r8 t! Z去打開一個檔案系統的節點5 ?1 T5 J2 A$ Y/ G
就可以用這個file descriptor的handler對他做mmap()的動作
" s4 _2 S% r* b那這個mmap究竟背後藏了哪些意義?5 Y# }) j" u0 s
又有哪些硬體在工作才能達成?/ j- R" }6 W0 |5 i1 a+ V
* k8 Q7 X7 t3 ]8 |- H; G' H1 Emmap的字面意義是memory map
1 G l* O: A# U! l顧名思義就是『記憶體映對』
8 y0 W6 B2 `3 A( e簡單來看,就是用mmap()幫你做對映
- Y2 c$ ^9 K. F5 z0 H+ ^3 H& B對映好了,對著傳回的address作存取
8 C) h' [; Z c! Z$ S5 ^就等於對檔案作存取9 h5 k& ^ ]$ @% g4 D; F$ @* E
+ G/ o* |: p* h3 H6 m! k1. 首先來看mmap()一般是怎麼被使用的 (這邊可以先不用管要傳什麼參數)" n$ a4 [! [* o/ f2 i
int fd, mapSize, offset, start;: I! k8 b* }( F0 I. @
char* ptr;
6 S; m: F4 ?6 I7 G
, c( k z1 m+ WmapSize = 0x1000; /* 希望映對多大的區塊 */: k/ C) D7 g7 [
offset = 0;4 C1 D7 C8 I* B+ w
start = 0;
8 r: a( C: K4 B- N/* 打開檔案 */
" }, [+ n7 t1 D, Gfd = open( "/home/tester/a.txt", O_RDWR | O_SYNC );
! R' D- I$ }( i7 c; L! D6 I# i/* 作mmap動作,取得一個對應好的address */
2 ^; f# @, }& h& a' \# \ptr = mmap( 0, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset );
$ j) S; T+ U4 R% Q0 e6 y% I* t1 j+ E" p! J# P$ R
假如一切順利的話 ptr 就會接到一個address,這個address會對應到a.txt這個檔案所在的起始位置,! N8 I+ @( E9 s
如果這時候我們用 strcpy( ptr, "hello!!" );
$ S, \! B# s9 c, D. k, U `
8 [5 R( M6 K v" F. J: O% Aa.txt裡面就會被寫入"hello!!"的字串3 |5 _+ j2 ?7 C, }1 @
) C% r3 r7 }" X6 ?) v, w+ E
2. 假如我寫了兩個程式,都是用mmap()到同一個a.txt,程式會不會出問題? 如果不會,那我既然對同一個檔案作mmap(),那我拿到的ptr不是應該是相同的address?
1 A m1 G1 U, l5 c j/ e2 s" M+ E8 `/ P9 V% |0 z
答案是:兩個程式可以正常執行,但是這兩個回傳的address不一定相同。
( \* j9 X; V7 v8 }( [( C- i" Q3 Xwhy? 為什麼對同一個檔案寫入,也都做同樣的mmap()動作,甚至傳的參數值都相同。) F, S4 T# G) ]* ?9 v
為什麼拿到的address可以是不同的? 更奇怪的是,位址不同,還是同樣寫到同一個檔案上頭。8 Q3 ^- t1 E' Q4 s
. X- K6 `0 `* ~4 ?假如這一切都是合理的,那表示雖然這兩個位址不一定相同,其實都是對映同一個地方,表示有某種東西記錄著這個對應關係。而且,兩個program的ptr有時候會一樣,可是有時候又不一樣。唯一個可能是表示兩個process各自保有這些映對的方式。# _3 u# q5 h! a. K5 n; A ~) @/ F
% j x7 v" O6 T: N: f$ t
3. 假設我只寫一個程式,但是mmap()兩次到同一個檔案上呢? 得到的兩個ptr會一樣嗎?9 _) m' [6 Z; I; V9 E/ R5 e9 W
* R% H ~6 C8 ~+ m6 _答案是:這個兩ptr還是不一樣的,兩個不同program 跑出來的mmap()結果不同也就算了,同一個program呼叫兩次mmap()跑出來的ptr也不一樣,但又都對映著相同的檔案a.txt。因此我們又可以猜測這一個mmap()是動態的,動態去產生一種應對的方式,將傳回的ptr對應到真正的檔案a.txt去,所以同一個process可以對應好幾次,好幾次都用不同的address去對映到相同的檔案上去。
9 k0 x4 {& G4 B5 E% @* X# Y2 S
/ e# S+ m9 n- Q2 R9 H綜合上面三種現象,我們合理的懷疑系統裡面存在了一個東西,它讓每一個process可以動態地記錄address的對應關係。並且,每個process各自擁有這個table,而這些對映的關係會動態的反應在這個table當中。( m. Z/ Y2 A' @) {+ j* I# [) k
( n. U1 B! N. p* p" i回想一下一個系統有誰會做這種工作,不就是MMU所擔任的重要角色嗎?
% ?4 U5 _5 y, D' N% U# K1 `每個process各自擁有自己的 page table 當他呼叫mmap()的時候,系統就動態地幫她在這個table上寫上紀錄著7 d* I# e/ C; s, l$ j/ J
2 }9 j1 d/ {: S[processA-pgtable]7 H; o. }+ n, S, k# E4 Y
0x00008000 ptr1 --> a.txt/ ]$ F9 L0 w: D! h- S# f
0xa0008000 ptr2 --> a.txt
! A: }: E4 D3 ]. P6 ^7 P) U7 Z9 b4 z& Y1 I, V; R- X
[processB-pgtable]
: Z R- [+ f2 Q/ f/ L& \0x00008000 ptr1 --> a.txt
' S/ T4 S0 V) E0 L( q+ M6 e* i a0xb0008000 ptr2 --> a.txt
2 r G8 c6 \+ b/ h6 R. s' ]; N6 A) V. J9 {
這樣ptr1, ptr2都可以對應到相同的地方,又因為各個process又有不同table,所以有時候ptr1有可能會相同。
4 X. [0 j# r7 _2 R如此一來,我們終於可以合理的解釋我們觀察mmap()為何對映出來的address會有如此的表現。原來就是MMU被加入,而且OS又被設計成每個process都會各自擁有一個page table來記錄他對記憶體如何解讀。 |
評分
-
查看全部評分
|