在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
害我白看了一上午virtualcopy,奶奶的原來不能用了。怪不得昌工讓我看流驅動