http://blog.csdn.net/fredzeng/archive/2007/04/04/1551898.aspx
在CE4.2/5.0里面滾打多年的兄弟應該經常用這個函數吧。這個函數方便驅動和應用程序范圍任何的物理地址,包括物理內存啊,設備控制器的寄存器啊,甚至GPIO也可以在AP里面隨便拉上拉下。
這個函數雖然方便,但是并不安全,你想你好不容易把一個功能完善的image給build出來了,結果碰到了一個寫AP的“高手”,把你的寄存器和共享內存中的數據修改得一塌糊涂,最后報出bug來說你驅動的你會不會暈倒!
還好從CE6.0開始我們可以安枕無憂了,因為AP再也不能調用VirtualCopy函數來直接訪問物理地址了,但因此帶來了一些應用上的不便。
VirtualCopy的限制來源于CE6.0之后kernel的巨大變革,在CE5.0之前的Windows CE操作系統中,kenrel就僅僅是kern.exe(nk.exe),這個exe其實是OAL、KITL和Kernel三個的合體,nk.exe是運行于內核模式(kernel mode),也就具有了訪問特殊地址的權限,然后除此之外的代碼默認都是運行于用戶模式(user mode),所以它們的驅動和AP都是等級的,都在用戶模式運行,要運行在kernel模式也可以,調用一個API SetKmode()就行了。因為驅動是肯定要訪問物理地址的,所以CE5.0以前的OS都是運行用戶模式的程式訪問物理地址的,然后又為了方便做從物理地址到虛擬地址的映射,就提供了一系列的幫助函數,virtualcopy就是最常用的函數之一。
CE6.0開始,kernel模式變得比較正規,類似于臺式機上的windows系統了,驅動和ap的權限是嚴格區分的,大部分的驅動程序運行在kernel模式,它們可以用virtualcopy讀寫物理地址對應的物理設備,但用戶模式的AP將從此沒有直接訪問物理地址的權限,virtualcopy每次調用都會失敗返回。
在這里還要注意的是,其實并不是用戶模式就不能使用virtualcopy,virtualcopy只是不能在用戶模式的AP中使用,但是卻還可以在用戶模式的驅動使用,但是在用戶模式的驅動中使用也有條件,那就是必須在對應的注冊表中設置可以訪問的內存地址的范圍才行。
在某些場合,一些特殊功能的AP確實需要訪問物理地址的,比如設置保存物理內存指定位置的全局變量,開發讀寫GPIO的測試工具等等。在這種情況下一種簡單的方法是實現一個最簡單的跑在kernel模式的流驅動,提供一個deviceiocontrol的接口來幫助AP申請對應于物理內存地址的虛擬內存地址。
除了virtualcopy之外,CE6下還有很多API是AP和user模式的驅動不能調用的,給大家參考一下,大家要把CE50下的AP移植到6.0下一定要注意找到替代
Virtual Memory APIs
CeVirtualSharedAlloc
LockPages
LockPagesEx
UnlockPages
UnlockPagesEx
VirtualAllocCopyEx
VirtualCopyEx
VirtualSetAttributes
CreateStaticMapping
NKDeleteStaticMapping
VirtualCopy
File System APIs
ReadRegistryFromOEM
SetStoreQueueBase
WriteRegistryToOEM
Power APIs
PowerOffSystem (很多測試AP用到)
Miscellaneous APIs
SetOOMEvent