大概說明空間的利用方式
記憶體管理就是管理記憶體位址空間 (memory address)。
32 bit 有 4G 的 address。
CE分成兩半來用,High-half 給 OS,Low-half給 Process。
Address 決定了,並不會立刻佔用phyical memory,直到這個Address的內容真得被利用到,才會真的把phyical memory mapping過來 (稱為 commit)。
CE 使用記憶體位址的規則是:
每個Process 有 32M 的 address 可以用。 但是要從 0x10000 開始用起。
由下往上依次是:
- Program Code
- Read Only Data
- Read Write Data
- Resource
- 預留的 Heap 空間
- 預留的 Stack 空間
RAM Base DLL 會從 32M 開始往下 Load。
=> 所以 Free Space 是被 Process Code, DATA, STACK 和 RAM-DLL 夾著。
process 在執行過程中如果create seperate heap或call VirtualAlloc 會接在剛剛"預留的STACK空間"上面開始,找第一個符合的位址區。
接著講 VirtualAlloc 這個API.
是以 1k 或 4k 為 alloc 的單位。同時會對齊 64k。 <== 這個點問題,應該要怎樣"以4k 為單位,而且對齊 64k? 對齊 64k 不就是以 64k 為單位?
所以下面的code在CE里會fail:
for(i=0;i<512;i++)
pMem[i] = VirtualAlloc(0,PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGER_READWRITE);
因為這樣實際上 會alloc 掉的記憶體(Address space and physical memory) 是 512 * 64k Byte.
超過 32M.
=>雖然你只需要 512 * 4k Byte
所以要利用 Allocate Address 和 Commite Physical Memory 兩段式動作的方式來作:
這樣就只會用掉 512*4k的位置空間了。(同時又commit到實際記憶體)
pBase = VirtualAlloc (0, 512 * PAGE_SIZE, MEM_RESERVE, PAGE_READWRITE);
for(i=0;i<512;i++)
pMem[i] = VirtualAlloc(pBase+(i*PAGE_SIZE),PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
接下來說明Load DLL 的記憶體使用情形
已經知道RAM-DLL 是從每個process的32M邊界往前(下)使用。
除此之外,所謂DLL,就是有"共用"的特性。所以有可以一個DLL被2個 process使用。
因為CE的同一個DLL在不同的Process中需要在相同的Virtual Address (why?)。
所以在load DLL的時候,必須考慮到避開其他process 的 DLL 已經使用的位址。
一個process只有32M已經很慘了,DLL還要考慮自己不用的DLL要避開!!Process Load A, B DLL -- Memory = A.B
Process Load A, C DLL -- Memory = A.(B).C
Process Load A, D DLL -- Memory = A.(B).(C).D
其中( )的部份在該process看來是空下來的部份
CE 5.0 是不是也是一樣?
4 則留言:
基本上是以從64K 對齊(到CE 5.0都是這樣, WM6 & WM6.1 都有針對這做一些修改, 因為Feature 越來越多, DLL 就很多, 會有不夠擺的情形), 然後4K 一個page這樣(透過VirtualAllocate), 例如你的 RAM DLL 會被載到 64K對齊的位址, 如果你的DLL 只有 1K, 下一個DLL也是被放到下一個64K對齊的地方(換句話說, 一個DLL最小佔據的空間就是64K) (WM6 改成4K為單位對齊
所以擺放在Virtual Address 時是以64K來對齊,然後commit physical時是以 4k 為單位囉?
沒錯, 可以直接追 \Private\winceos\nk\kernel 下的 virmem.c 這是CE5.0 目錄結構, 我想 4.2 管理機制應該一致
喔,感激感激 :)
張貼留言