為了使讀者能夠詳細了解wince的位址對映原理還有兩種模式,在這裡我分幾個部分說明:
1、 wince核心nk.exe的任務是管理作業系統核心功能。按照oemaddresstable的對映要求,所有實體地址都對映到0x80000000以上,所以對於核心程式nk.exe和核心模式下的執行緒來說,只要訪問0x80000000以上的有效虛擬位址經mmu就能夠訪問實體地址,無需再對映是核心模式的乙個特點。核心模式的第二個特點是沒有位址訪問限制,核心模式執行緒可以訪問任何有效虛擬位址,所謂有效虛擬位址是指有實際事物對應。
2、使用者模式執行緒只能訪問0x80000000以下的虛擬位址空間,wince6.0之前版本的核心為每個程序劃分32mb的位址空間,在不呼叫特殊函式的情況下不能相互訪問,這樣的設計使得wince系統更安全、更穩定,限制訪問位址是使用者模式的第乙個特點。第二個特點就是需要多一層對映,如果執行緒要訪問物理記憶體的話需要先對映到0x80000000以上,再經mmu訪問物理記憶體位址。
wince的執行緒具有轉移性(參考 api getcallerprocess的說明,有乙個很好的例子),當應用程式的執行緒呼叫api或者呼叫驅動程式介面函式時,該執行緒會轉移到 gwes.exe、device.exe、filesys.exe等程序中執行,轉移是由wince核心操作的,它會修改執行緒的上下文,記錄執行緒的當前程序、呼叫者程序、擁有者程序三個值。
在onbutton1()中編寫
dword oldmode = setkmode(false);
volatile int *pitemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)
*pitemp = 12345;
在onbutton2()中編寫
dword oldmode = setkmode(false);
volatile int *pitemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)
int itemp = *pitemp;
先只執行onbutton1()然後關閉程式,再重啟程式然後執行onbutton2(),itemp仍然等於12345。結果說明了兩點:核心模式執行緒可以直接訪問0x80000000以上的有效虛擬位址;我們寫到ram中的資料沒有丟失,說明虛擬位址有效。
如果在定製核心的時候沒有選擇「full kernel mode」,那麼在這個核心上執行的所有執行緒都處於使用者模式。可以呼叫setkmode(true)使呼叫執行緒暫時處於核心模式,還是原來的假設環境,我再舉個例子:
在onbutton1()中編寫
dword oldmode = setkmode(true);
volatile int *pitemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)
*pitemp = 12345;
在使用者模式下,如果不呼叫setkmode(true),那麼執行*pitemp = 12345一定會彈出對話方塊,提示位址訪問非法,如果呼叫setkmode(true)就不會提示位址訪問非法,而且在onbutton2()中仍然能得到12345這個值。
通過這兩個例子我相信讀者能夠完全了解兩種模式的區別了。
4、 wince提供了兩個函式setkmode和setprocpermissions,其中setkmode能夠把呼叫執行緒切換到核心模式,還可以切換回使用者模式。setprocpermissions + getcurrentpermissions新增當前程序訪問許可權給呼叫執行緒, setprocpermissions (0xffffffff)能讓呼叫執行緒訪問所有程序空間,但是呼叫執行緒仍然處於使用者模式。setkmode和 setprocpermissions函式使得使用者模式的特點不那麼明晰。
如上所說乙個應用程式的執行緒可能轉移到其它兩個程序位址空間中讀寫資料,而每乙個執行緒在被建立的時候只有訪問建立它的程序位址空間的許可權,所以驅動程式開發者必須在驅動程式讀寫資料前呼叫setkmode或者 setprocpermissions增加呼叫此函式的執行緒訪問其它程序空間的許可權。如果乙個應用程式的執行緒只轉移到乙個程序位址空間,一般為裝置管理器程序device.exe,這種情況下不必增加執行緒訪問其它程序空間的許可權,但如果驅動程式本身建立了乙個執行緒,那還是要呼叫setkmode或者 setprocpermissions增加新的執行緒訪問其它程序的許可權的,因為驅動程式建立執行緒時,當前程序為裝置管理器,所以新執行緒只具有訪問裝置管理器程序空間的許可權,而不具備訪問應用程式程序空間的許可權。
為了讓讀者能了解其中的原因,我舉個例子:
假設裝置管理器被載入到slot4,應用程式a被載入到slot 8,a只有乙個主線程t,t開始執行,按照wince的規定,正獲得cpu的程序必須對映到slot0,那麼在執行**的時候 a的所有虛擬位址都被減去乙個偏移值,也就是8×0x02000000,a呼叫deviceiocontrol,傳遞乙個指向乙個結構體的指標b,而這個結構體中包含乙個指標c,指標c包含的位址假設為0x00030000,當執行deviceiocontrol時wince把裝置管理器的程序位址空間對映到slot0,因為放在登錄檔[hklm/drivers/builtin]下的驅動程式是由裝置管理器載入的,自然驅動程式的**段被載入到裝置管理器程序空間,但是執行緒仍然是t,此時t的當前所在程序為裝置管理器(currentprocess),a變成了t的呼叫者程序(callerprocess),t自動具有了訪問呼叫者程序空間的許可權。這時訪問slot0中的虛擬位址其實質就是訪問裝置管理器的程序位址空間,要把位址加上乙個偏移值,也就是4×0x02000000,所以deviceiocontrol訪問指標c包含的位址時本應該加上8×0x02000000,卻加上4×0x02000000,結果位址並不是裝置管理器的合法區域,系統就會提示位址訪問非法。而如果做了乙個對映,指標c包含的位址就會被加乙個正確的偏移值,使位址處於a的位址空間slot 8中,t此時具有訪問a程序空間的許可權,訪問到正確的虛擬位址當然會得到正確的資料了。
Linux使用者模式和核心模式
ms dos等作業系統在單一的cpu模式下執行,但是一些類unix的作業系統則使用了雙模式,可以有效地實現時間共享。在linux機器上,cpu要麼處於受信任的核心模式,要麼處於受限制的使用者模式。除了核心本身處於核心模式以外,所有的使用者程序都執行在使用者模式之中。核心模式的 可以無限制地訪問所有處...
linux的使用者模式和核心模式
ms dos等作業系統在單一的cpu模式下執行,但是一些類unix的作業系統則使用了雙模式,可以有效地實現時間共享。在linux機器上,cpu要麼處於受信任的核心模式,要麼處於受限制的使用者模式。除了核心本身處於核心模式以外,所有的使用者程序都執行在使用者模式之中。核心模式的 可以無限制地訪問所有處...
使用者模式與核心模式
首先了解一下使用者模式和核心模式。一般說來,程序既可在使用者模式下執行,又可在核心模式下執行。核心模式的許可權高於使用者模式的許可權。程序每次呼叫乙個系統呼叫時,程序的執行方式都發生變化 從使用者模式切換到核心模式,然後繼續執行。可見 乙個程序在cpu上執行可以有兩種執行模式 程序狀態 使用者模式和...