微軟有一篇文檔
《Virtual Memory Layout: Windows CE 5.0 vs. Windows Embedded CE 6.0 》
非常不錯
這裏特意翻譯成中文給大家參考
由於翻譯水平有限,有問題歡迎討論
轉載請註明出自ARMCE
這裏是PDF版本,因爲有表格,所以整個複製在這裏會格式很差,推薦看PDF
http://www.armce.com/bbs/thread-1133-1-1.html
這個是原創制作的WinCE6虛擬內存佈局圖
下面內容格式可能有問題,僅供預覽,還請下載上面的pdf版本
WinCE5與WinCE6的虛擬內存佈局
wwfiney@ARMCE
在WinCE6之前,進程(process)有最多32個,及每個進程只能有32MB虛擬內存(virtual memory)的限制,並且所有的進程共享相同的4GB地址空間。對於CE6,內核進程存在於4GB(32-bit)虛擬地址空間的高2GB空間內,並且底部的2GB空間對於每一個進程都是唯一的。由於可創建的句柄數量的原因,進程有最多32000個的限制。但是實際應用當中,限制進程數量的往往是物理內存大小。
在以前版本的WinCE中,當前進程使用Slot0。在WinCE6裏面,Slot0和其他進程Slot一樣,都各有2GB的有效空間。
由於虛擬內存的存取是硬件通過內存管理單元(MMU)來實現的,所以虛擬內存編碼是CPU相關的。與其他使用軟件TLB(translation look-aside buffer)的CPU體系不同,ARM和X86體系的CPU使用硬件頁表,所以虛擬內存的存取是通過硬件直接進行的。
下面列出WinCE6在虛擬內存管理方面的設計目標:
? 每個進程擁有大的虛擬內存
? 沒有預設的進程數限制
? 進程間的保護
? 最小的CPU相關代碼
? 高效的虛擬內存分配
? 高效的TLB miss處理
下表列出CE6.0的虛擬內存分佈
模式 地址範圍 大小 描述 註釋
內核模式 0xF0000000 - 0xFFFFFFFF 256 MB CPU特定的虛擬內存空間 系統呼叫陷阱區域
內核數據頁
內核模式 0xE0000000 - 0xEFFFFFFF 256 MB 內核虛擬地址 CPU相關 內核空間虛擬地址 有些CPU體系禁止了這塊地址,如SHx
內核模式 0xD0000000 - 0xDFFFFFFF 256 MB 內核虛擬地址 內核空間地址,由所有被內核加載的服務和驅動共享
內核模式 0xC8000000 - 0xCFFFFFFF 128 MB 對象存儲(Object store) RAM存儲空間,爲RAM文件系統,CEDB數據庫,RAM註冊表服務
內核模式 0xC0000000 - 0xC7FFFFFF 128 MB 內核XIP的DLL XIP的Dll,服務於內核及所有由內核加載的服務和驅動
內核模式 0xA0000000 - 0xBFFFFFFF 512 MB 非緩存的靜態映射地址 不通過CPU緩存直接訪問物理內存
內核模式 0x80000000 - 0x9FFFFFFF 512 MB 緩存的靜態映射地址 通過CPU緩存來訪問物理內存
用戶模式 0x7FF00000 - 0x7FFFFFFF 1 MB 未映射,作爲保護 用戶模式與內核模式之間的緩衝地址
用戶模式 0x70000000 - 0x7FEFFFFF 255 MB 共享的系統堆(heap) 內核與進程之間共享的堆(heap)空間 內核及其服務可以在這個堆上寫入 用戶進程只能讀取(Read-only) 允許一個進程從服務端(server)獲得數據而不用進行一次內核呼叫
用戶模式 0x60000000 - 0x6FFFFFFF 256 MB 使用RAM的映射文件(RAM-backed map files) 爲了向後兼容,使用RAM的映射文件被映射在固定在位置。
使用RAM的映射文件是指那些沒有分配實際文件的內存映射文件
調用CreateFileMapping,並且hFile爲INVALID_HANDLE_VALUE時可以得到這種內存映射文件
這個區域是給使用這種內存映射文件來作爲進程間通信手段的應用程序提供向後兼容
用戶模式 0x40000000 - 0x5FFFFFFF 512 MB 用戶模式的Dll代碼及數據 Dll是從地址底部開始加載並往上增長
? 起始地址爲0x40000000.
? 代碼和數據是交織在一起的
? 被多個進程加載的同一個dll在各進程間使用相同的地址
? 代碼頁共享相同的物理內存頁
? 每個進程有自己獨立的物理內存頁給數據頁部分
用戶模式 0x00010000 - 0x3FFFFFFF 1 GB 進程及用戶分配的虛擬地址 進程的可執行代碼及數據
用戶的虛擬內存分配起始地址是在進程的代碼及數據段之後,並且是向上增長(言下之意代碼及數據段是放在最下面)
用戶模式 0x00000000 - 0x00010000 64 KB CPU相關的用戶內核數據 對於用戶而言,用戶內核數據永遠是隻讀的
根據CPU體系的不同,用戶內核數據可以被內核讀寫(ARM),或者只讀(其他CPU體系)
關於上面的表格有以下幾個要點需要注意:
? 用戶模式Dll現在是從0x40000000開始往上(高地址)增長,而不是往下增長了
? 用戶調用虛擬內存相關的函數只能操作由VirtualAlloc分配的空間,而不能再操作內核模式分配在用戶空間的虛擬內存,例如棧(stacks),內存映射文件(memory-mapped file views),以及Dll代碼及數據
? 共享堆區域對於內核是可讀寫的,而對於用戶進程是隻讀的。這塊區域是用來提高系統與客戶端進程通信效率的。但是由於所有進程都可以讀取這塊區域,所以不要放任何安全相關的數據,比如密碼等
? 區域之間至少有64KB的沒有映射的空間以防止越界訪問(注:這裏的區域之間我理解爲內核與用戶模式之間,即那1MB的空間)
用戶進程的虛擬內存接口
在某一時刻,一個虛擬地址只能被映射一次。你不能通過其他進程的虛擬地址直接存取該進程的存儲區。虛擬內存函數只能用在由一個進程分配的地址上。舉例來說,一個應用程序不能調用VirtualProtect去改變自己的代碼段的保護屬性
帶Ex的函數版本是服務端用來存取客戶端進程虛擬地址的
下面這些函數組成了用戶進程可用的虛擬內存操作接口:
? VirtualAlloc
? VirtualAllocEx
? VirtualFree
? VirtualFreeEx
? VirtualProtect
? VirtualQuery
? WriteProcessMemory
? ReadProcessMemory
? VirtualProtectEx
? VirtualQueryEx
內核模式虛擬內存操作接口
下面帶Ex的函數版本使用進程句柄作爲參數,來操作其他進程的虛擬內存。下表是內核模式的虛擬內存操作接口:
? VirtualCopy
? VirtualCopyEx
? LockPages
? UnlockPages
? CeVirtualSharedAlloc
? AllocPhysMem
? CreateStaticMapping
? VirtualSetAttributes
? DeleteStaticMapping
使用這種虛擬內存佈局的好處
? 進程總數不再限定在32個
? 每個進程可用的地址空間不再限定在32MB
? 由於使用硬件頁表,ARM和X86結構的CPU在進程切換上速度更快了,但是MIPS和SHx的CPU幾乎沒有變化
? 由於簡化了地址空間存取檢查,TLB miss處理在MIPS和SHx的CPU上速度有所提升,但是ARM和X86上幾乎沒有變化
虛擬內存佈局帶來的折衷
? 各進程的虛擬內存空間不再總是可以訪問的了,但是內核進程和當前用戶進程的虛擬內存空間卻總是可以訪問的。因此,存取其他進程的存儲空間,特別是傳遞給服務端的buffer,已經不是進行簡單的映射指針就可以處理了
? 更復雜的引用計數
? 更復雜的進程間通信和buffer傳遞