轉(zhuǎn)windows的文件裝入_第1頁(yè)
轉(zhuǎn)windows的文件裝入_第2頁(yè)
轉(zhuǎn)windows的文件裝入_第3頁(yè)
轉(zhuǎn)windows的文件裝入_第4頁(yè)
轉(zhuǎn)windows的文件裝入_第5頁(yè)
已閱讀5頁(yè),還剩7頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、轉(zhuǎn) windows的文件裝入兼容內(nèi)核十:Windows的進(jìn)程創(chuàng)建和映像裝入轉(zhuǎn)自:融windows和linux于一體。niubi Windows的進(jìn)程創(chuàng)建和映像裝入的過程,Microsoft Windows Internals 4e一書的第六章中有頗為詳細(xì)的說明。本文就以此為依據(jù),夾譯、夾敘、夾議地作一介紹。書中說,創(chuàng)建進(jìn)程的過程分成六個(gè)階段,發(fā)生于操作系統(tǒng)的三個(gè)部分中,那就是:Windows客戶端即某個(gè)應(yīng)用進(jìn)程的包括Kernel32.dll在內(nèi)的動(dòng)態(tài)連接庫(kù),Windows的執(zhí)行體、即內(nèi)核確切地說是內(nèi)核的上層,以及Windows子系統(tǒng)的服務(wù)進(jìn)程Csrss中。這六個(gè)階段是:1.打開目標(biāo)映像文件。2

2、.創(chuàng)建Windows的執(zhí)行體進(jìn)程對(duì)象,也就是內(nèi)核中的進(jìn)程控制塊數(shù)據(jù)結(jié)構(gòu)。3.創(chuàng)建該進(jìn)程的初始第一個(gè)線程,包括其堆棧、上下文、以及執(zhí)行體線程對(duì)象,即內(nèi)核中的線程控制塊數(shù)據(jù)結(jié)構(gòu)。4.將新建進(jìn)程通知Windows子系統(tǒng)。5.啟動(dòng)初始線程地運(yùn)行除非因?yàn)閰?shù)中的CREATE_SUSPENDED標(biāo)志位為1而一創(chuàng)建便被掛起。6.在新進(jìn)程和線程的上下文中完成用戶空間的初始化,包括裝入所需的DLL,然后開始目標(biāo)程序的運(yùn)行。下面分階段敘述。第一階段:打開目標(biāo)映像文件在Win32位API中,創(chuàng)建進(jìn)程是由CreateProcess完成的。這實(shí)際上是個(gè)宏定義,根據(jù)不同的情況定義成CreateProcessA或Creat

3、eProcessW之一,這兩個(gè)函數(shù)都在kernel32.dll中可以用工具depends觀察。兩個(gè)函數(shù)的區(qū)別僅在于字符串的表達(dá),前者采用ASCII字符,而后者采用寬字符、即Unicode。實(shí)際上Windows的內(nèi)部都采用寬字符,所以前者只是把字符串轉(zhuǎn)換成寬字符格式,然后調(diào)用后者??梢栽赪indows上運(yùn)行的可執(zhí)行軟件有好幾類,處理的方法自然就不一樣:lWindows的32位.exe映像,直接運(yùn)行。lWindows的16位.exe映像,啟動(dòng)ntvdm.exe,以原有命令行作為參數(shù)。lDOS的.exe、.com、或.pif映像,啟動(dòng)ntvdm.exe,以原有命令行作為參數(shù)。lDOS的.bat或.c

4、md批命令文件腳本,啟動(dòng)cmd.exe,以原有命令行作為參數(shù)。lPOSIX可執(zhí)行映像,啟動(dòng)posix.exe,以原有命令行作為參數(shù)。lOS/2可執(zhí)行映像,啟動(dòng)os2.exe,以原有命令行作為參數(shù)。這里面最重要的當(dāng)然是32位的.exe映像,而最后兩類現(xiàn)在已經(jīng)很少見了。從對(duì)于除32位.exe以外的各種映像的處理,讀者不妨對(duì)比一下Wine對(duì).exe映像的處理,看看這里有著什么樣的相似性。當(dāng)然,我們?cè)谶@里只關(guān)心32位.exe映像。對(duì)于這一類映像,CreateProcess首先打開映像文件,再為其分配創(chuàng)建一個(gè)Section、即內(nèi)存區(qū)間。創(chuàng)建內(nèi)存區(qū)間的目的當(dāng)然是要把映像文件影射到這個(gè)區(qū)間,不過此時(shí)還不忙著

5、映射,還要看看。看什么呢?首先是看已經(jīng)打開的目標(biāo)文件是否一個(gè)合格的.exe映像萬一是DLL映像?。還要看的事就有點(diǎn)出乎讀者意外了,看的是在注冊(cè)表中的這個(gè)路徑:HKLMSOFTWAREMicrosoftWindows NTCurrentVersionImage Options用depends可以看到,ntdll.dll中有個(gè)函數(shù)LdrQueryImage,就是專門干這個(gè)事的。如果上述路徑下有以目標(biāo)映像文件的文件名和擴(kuò)展名為鍵的表項(xiàng),例如image.exe,而表項(xiàng)中又有名為Debugger的值,那么這個(gè)值一個(gè)字符串就替換了原來的目標(biāo)文件名,變成新的目標(biāo)映像名,并重新執(zhí)行上述的第一階段操作。這樣做的

6、目的當(dāng)然是為調(diào)試程序提供方便,但是我們不妨設(shè)想:如果黑客或某個(gè)木馬程序設(shè)法在注冊(cè)表中加上了一個(gè)表項(xiàng)?這時(shí)候用戶以為是啟動(dòng)了程序A,而實(shí)際啟動(dòng)的卻是B!。第二階段:創(chuàng)建內(nèi)核中的進(jìn)程對(duì)象我們知道,Linux上的每個(gè)進(jìn)程線程都有一個(gè)進(jìn)程控制塊、即task_struct數(shù)據(jù)結(jié)構(gòu),與具體進(jìn)程/線程有關(guān)的絕大部分信息都集中存儲(chǔ)在這個(gè)數(shù)據(jù)結(jié)構(gòu)中。而Windows則有所不同。首先,Windows的進(jìn)程和線程各有不同的對(duì)象、即數(shù)據(jù)結(jié)構(gòu),從概念上把線程和進(jìn)程分離開來。線程是具體的執(zhí)行上下文,是CPU調(diào)度的單位和目標(biāo),而進(jìn)程只是若干共享地址空間和特性如調(diào)度優(yōu)先級(jí)的線程的集合。于是,進(jìn)程有進(jìn)程的數(shù)據(jù)結(jié)構(gòu),線程有線程的

7、數(shù)據(jù)結(jié)構(gòu)。這就好像是對(duì)一組task_struct數(shù)據(jù)結(jié)構(gòu)提取公因子所形成的結(jié)果,這個(gè)舉措是很好理解的。進(jìn)一步,Windows又把本可集中存儲(chǔ)的的進(jìn)程數(shù)據(jù)結(jié)構(gòu)也拆分成好幾個(gè)對(duì)象,有的在內(nèi)核中,有的則在用戶空間。內(nèi)核中與進(jìn)程有關(guān)的對(duì)象有:lEPROCESS。即struct_EPROCESS,在Internals書中也稱為Process Block。它代表著Windows的一個(gè)進(jìn)程,E表示Executive,微軟把Windows內(nèi)核中的上層稱為Executive、以區(qū)別于下層的設(shè)備驅(qū)動(dòng)和內(nèi)存管理等成分、一般翻譯成執(zhí)行體。Executive也有管理、運(yùn)行的意思所以CEO就是總裁。lKPROCESS。這

8、是EPROCESS內(nèi)部的一個(gè)成分,其名稱就叫Pcb。lW32PROCESS。下面將要講到,在用戶空間有個(gè)Windows子系統(tǒng)的服務(wù)進(jìn)程csrss。這個(gè)服務(wù)進(jìn)程為系統(tǒng)中的每個(gè)Windows應(yīng)用進(jìn)程都維持著一個(gè)數(shù)據(jù)結(jié)構(gòu),其中包含了一些與窗口和圖形界面有關(guān)的信息。而對(duì)于窗口和圖形界面的操作原來也是由csrss在客戶進(jìn)程的請(qǐng)求下實(shí)現(xiàn)的。但是,為了提高效率,后來把這部分功能移到了內(nèi)核中。與此相應(yīng),有關(guān)數(shù)據(jù)結(jié)構(gòu)的一部分也需要移到內(nèi)核中,就成了W32PROCESS。既然KPROCESS是EPROCESS一部分,實(shí)際上內(nèi)核中與進(jìn)程有關(guān)的對(duì)象實(shí)際上只有兩種,就是EPROCESS和W32PROCESS。不過這里沒

9、有包括打開對(duì)象表,那也是每個(gè)進(jìn)程都有的(Linux內(nèi)核中的打開文件表也在進(jìn)程控制塊的外面。用戶空間與進(jìn)程有關(guān)的對(duì)象有:l如上所述,把W32PROCESS數(shù)據(jù)結(jié)構(gòu)移入內(nèi)核以后,csrss仍需要為每個(gè)Windows進(jìn)程保持一些別的信息,所以csrss內(nèi)部仍有按進(jìn)程的相應(yīng)數(shù)據(jù)結(jié)構(gòu)。lPEB(Process Environment Block)、即進(jìn)程環(huán)境塊。PEB中記錄著進(jìn)程的運(yùn)行參數(shù)、映像裝入地址等等信息。PEB在用戶空間中的位置是固定的,總是在0x7ffdf000。在Windows中,用戶空間和系統(tǒng)空間的分界線是2GB、即0x 80000000,所以PEB在靠近用戶空間頂端的地方。Interna

10、ls書中并未給出有關(guān)數(shù)據(jù)結(jié)構(gòu)的定義,但是通過Debug手段給出了EPROCESS的內(nèi)部結(jié)構(gòu):+0x000Pcb:_KPROCESS+0x06cProcessLock:_EX_PUSH_LOCK+0x070CreateTime:_LARGE_INTEGER+0x078ExitTime:_LARGE_INTEGER+0x080RundownProtect:_EX_RUNDOWN_REF+0x084UniqueProcessId:Ptr32Void+0x088ActiveProcessLinks:_LIST_ENTRY+0x090QuotaUsage:3Uint4B+0x09cQuotaPeak:3

11、Uint4B+0x0a8CommitCharge:Uint4B+0x0acPeakVirtualSize:Uint4B+0x0b0VirtualSize:Uint4B+0x0b4SessionProcessLinks:_LIST_ENTRY+0x0bcDebugPort:Ptr32Void+0x0c0ExceptionPort:Ptr32Void+0x0c4ObjectTable:Ptr32_HANDLE_TABLE+0x0c8Token:_EX_FAST_REF+0x0ccWorkingSetLock:_FAST_MUTEX+0x0ecWorkingSetPage:Uint4B+0x0f0A

12、ddressCreationLock:_FAST_MUTEX+0x110HyperSpaceLock:Uint4B+0x114ForkInProgress:Ptr32_ETHREAD+0x118HardwareTrigger:Uint4B可見,EPROCESS的第一個(gè)成分是Pcb,其類型是_KPROCESS、即KPROCESS,這是一個(gè)大小為0x6c的數(shù)據(jù)結(jié)構(gòu)。書中也給出了它的內(nèi)部結(jié)構(gòu)。Undocumented Windows 2000 Secrets一書也以Debug手段給出了這個(gè)數(shù)據(jù)結(jié)構(gòu)的內(nèi)部結(jié)構(gòu),但是列出的結(jié)構(gòu)與此有很大的不同,也許是因?yàn)榘姹镜年P(guān)系。從所列的內(nèi)容看,似乎Secrets一書

13、倒是正確的,因?yàn)槟抢锼械腅PROCESS結(jié)構(gòu)中有關(guān)于虛存的成分Vm,是一個(gè)大小為0x50的數(shù)據(jù)結(jié)構(gòu),而這里沒有,但是虛存地址空間顯然是進(jìn)程的主要資源,所以EPROCESS數(shù)據(jù)結(jié)構(gòu)中理應(yīng)有它的位置。由此看來,Secrets一書所述更接近于桌面和服務(wù)器系統(tǒng)的現(xiàn)實(shí),而Internals書中所列可能更接近于不帶MMU的嵌入式系統(tǒng)。而且,Secrets一書還在附錄C中給出了通過逆向工程手段得到的EPROCESS和PEB等數(shù)據(jù)結(jié)構(gòu)的定義代碼,這當(dāng)然是很有價(jià)值的。那么,如果確有不同版本的EPROCESS,這會(huì)有什么影響呢?首先,用戶空間的應(yīng)用程序不能直接訪問內(nèi)核中的EPROCESS數(shù)據(jù)結(jié)構(gòu),所以具體的EP

14、ROCESS數(shù)據(jù)結(jié)構(gòu)屬于內(nèi)核的內(nèi)部實(shí)現(xiàn),只要內(nèi)核中的各種成分、各個(gè)環(huán)節(jié)都配套成龍,自圓其說,就沒有什么問題,這跟Linux內(nèi)核中一些條件編譯和裁剪的效果是類似的??墒?,另一方面,對(duì)于可以動(dòng)態(tài)裝入的.sys模塊,如果在模塊中需要訪問這些數(shù)據(jù)結(jié)構(gòu),那就可能有問題了,因?yàn)?sys模塊都是以二進(jìn)制映像的形式提供的,不像在Linux中那樣可以由源代碼重新編譯。怎么辦呢?我們可以到Windows的DDK中去找找答案。在DDK的.h文件中,有函數(shù)IoGetCurrentProcess的申明:NTKERNELAPI PEPROCESS IoGetCurrentProcess VOID);這個(gè)函數(shù)是內(nèi)核為.sy

15、s模塊提供的支撐函數(shù),相當(dāng)于由Linux內(nèi)核導(dǎo)出的函數(shù)。其返回值類型是PEPROCESS,就是指向EPROCESS數(shù)據(jù)結(jié)構(gòu)的指針。顯然,這跟Linux內(nèi)核中的current相似,調(diào)用的目的是獲取當(dāng)前進(jìn)程的EPROCESS數(shù)據(jù)結(jié)構(gòu)指針。但是,DDK的.h文件中卻并未給出EPROCESS數(shù)據(jù)結(jié)構(gòu)的定義,所以調(diào)用這個(gè)函數(shù)所得到的僅僅是個(gè)指針,實(shí)際上與void*并無區(qū)別。這意味著在.sys模塊中是不允許直接訪問其內(nèi)部成分的。那么,.sys模塊如何使用這個(gè)指針呢?下面就是一個(gè)例子,還是在DDK中:NTKERNELAPI VOID MmProbeAndLockProcessPages IN OUT PMD

16、L MemoryDescriptorList,IN PEPROCESS Process,IN KPROCESSOR_MODE AccessMode,IN LOCK_OPERATION Operation);這個(gè)函數(shù)的作用是鎖定某個(gè)進(jìn)程的某些存儲(chǔ)頁(yè)面不讓換出,其輸入?yún)?shù)之一就是指向該進(jìn)程的EPROCESS結(jié)構(gòu)的指針。當(dāng)然,這個(gè)函數(shù)也是由內(nèi)核提供的屬于我們所說的設(shè)備驅(qū)動(dòng)界面。所以指針的提供者和使用者都是內(nèi)核,只要這二者配套即可,.sys模塊在這里只不過是傳遞了一下,所以也不會(huì)有問題。假定proc是指向進(jìn)程控制塊的指針,并且進(jìn)程控制塊中有個(gè)成份X,是個(gè)整數(shù),那么在Linux的動(dòng)態(tài)安裝模塊中可以直接用

17、proc-X訪問這個(gè)成分,但是在Windows的.sys模塊中則只能通過類似于get_X、set_X一類的支撐函數(shù)訪問這個(gè)成分。將數(shù)據(jù)結(jié)構(gòu)的內(nèi)容跟對(duì)于這些內(nèi)容的操作(method)相分離,正是對(duì)象與數(shù)據(jù)結(jié)構(gòu)的區(qū)別所在。而將數(shù)據(jù)結(jié)構(gòu)的內(nèi)容封裝起來,也正是微軟所需要的,因?yàn)樗辉敢夤_這些數(shù)據(jù)結(jié)構(gòu)。對(duì)于兼容內(nèi)核的開發(fā),這意味著我們不必拘泥于采用與Windows完全一致的EPROCESS數(shù)據(jù)結(jié)構(gòu)盡管Secrets的附錄C已經(jīng)給出了它的定義,一些內(nèi)部的操作和處理也不必完全與之相同,而只要與DDK所規(guī)定的界面相符就可以了。了解了有關(guān)的進(jìn)程對(duì)象,我們可以言歸正傳了。所謂創(chuàng)建內(nèi)核中的進(jìn)程對(duì)象,實(shí)際上就是創(chuàng)建

18、以EPROCESS為核心、為基礎(chǔ)的相關(guān)數(shù)據(jù)結(jié)構(gòu),這就是系統(tǒng)調(diào)用NtCreateProcess要做的事情,主要包括:l分配并設(shè)置EPROCESS數(shù)據(jù)結(jié)構(gòu)。l其他相關(guān)的數(shù)據(jù)結(jié)構(gòu)的設(shè)置,例如打開對(duì)象表。l為目標(biāo)進(jìn)程創(chuàng)建初始的地址空間。l對(duì)目標(biāo)進(jìn)程的內(nèi)核進(jìn)程塊KPROCESS進(jìn)行初始化。l將系統(tǒng)DLL的映像映射到目標(biāo)進(jìn)程的用戶地址空間。l將目標(biāo)進(jìn)程的映像映射到其自身的用戶空間。l設(shè)置好目標(biāo)進(jìn)程的進(jìn)程環(huán)境塊PEB。l映射其他需要映射到用戶空間的數(shù)據(jù)結(jié)構(gòu),例如與當(dāng)?shù)卣Z(yǔ)言支持、即NLS有關(guān)的數(shù)據(jù)結(jié)構(gòu)。l完成EPROCESS創(chuàng)建,將其掛入進(jìn)程隊(duì)列注意受調(diào)度的是線程隊(duì)列而不是進(jìn)程隊(duì)列。這里將系統(tǒng)DLL、實(shí)際上是

19、ntdll.dll、映射到目標(biāo)進(jìn)程的用戶空間是很關(guān)鍵的。這是因?yàn)?,除別的、主流的功能和作用外,ntdll.dll同時(shí)也起著相當(dāng)于Linux中ELF解釋器的作用,也擔(dān)負(fù)著為目標(biāo)映像建立動(dòng)態(tài)連接的任務(wù)。值得注意的是,NtCreateProcess與CreateProcess不同。CreateProcess創(chuàng)建一個(gè)進(jìn)程并使其初始線程運(yùn)行,除非在創(chuàng)建時(shí)就指定要將其掛起。而NtCreateProcess,則只是在內(nèi)核中創(chuàng)建該進(jìn)程的EPROCESS數(shù)據(jù)結(jié)構(gòu)并為其建立起地址空間。這只是個(gè)空殼架子,因?yàn)闆]有線程就談不上運(yùn)行,調(diào)度的目標(biāo)是線程而不是線程。而且,對(duì)NtCreateProcess的調(diào)用還有個(gè)條件,那

20、就是目標(biāo)映像已經(jīng)被映射到一個(gè)存儲(chǔ)區(qū)間(Section)中。第三階段:創(chuàng)建初始線程如上所述,進(jìn)程只是個(gè)空架子,實(shí)際的運(yùn)行實(shí)體是里面的線程。所以下一步就是創(chuàng)建目標(biāo)進(jìn)程的初始線程,即其第一個(gè)線程。與EPROCESS相對(duì)應(yīng),線程的數(shù)據(jù)結(jié)構(gòu)是ETHREAD,并且其第一個(gè)成分是數(shù)據(jù)結(jié)構(gòu)KTHREAD,稱為TCB。同樣,Internals和Secrets兩本書中所列的ETHREAD內(nèi)部結(jié)構(gòu)有所不同,后者的附錄C中給出了通過逆向工程得到的ETHREAD數(shù)據(jù)結(jié)構(gòu)定義。同樣,從Windows DDK中申明的一些函數(shù)也可以看出,.sys模塊只是傳遞ETHREAD指針或KTHREAD指針由于KTHREAD是ETHRE

21、AD中的第一個(gè)成分,二者實(shí)際上是一回事,而不會(huì)直接訪問它的具體成分。PKTHREAD NTAPI KeGetCurrentThread();NTKERNELAPI KPRIORITY KeQueryPriorityThread(IN PKTHREAD Thread);NTKERNELAPI LONG KeSetBasePriorityThread(IN PKTHREAD Thread,IN LONG Increment);NTKERNELAPIPDEVICE_OBJECT IoGetDeviceToVerify(IN PETHREAD Thread);此外,就像進(jìn)程有進(jìn)程環(huán)境塊PEB一樣,線程

22、也有線程環(huán)境塊TEB,KTHREAD結(jié)構(gòu)中有個(gè)指針指向其存在于用戶空間的TEB。前面講過,PEB在用戶空間的位置是固定的,PEB下方就是TEB,進(jìn)程中有幾個(gè)線程就有幾個(gè)TEB,每個(gè)TEB占一個(gè)4KB的頁(yè)面。這個(gè)階段的操作是通過系統(tǒng)調(diào)用NtCreateThread完成的,主要包括:l創(chuàng)建和設(shè)置目標(biāo)線程的ETHREAD數(shù)據(jù)結(jié)構(gòu),并處理好與EPROCESS的關(guān)系例如進(jìn)程塊中的線程計(jì)數(shù)等等。l在目標(biāo)進(jìn)程的用戶空間創(chuàng)建并設(shè)置目標(biāo)線程的TEB。l將目標(biāo)線程在用戶空間的起始地址設(shè)置成指向Kernel32.dll中的BaseProcessStart或BaseThreadStart,前者用于進(jìn)程中的第一個(gè)線程,

23、后者用于隨后的線程。用戶程序在調(diào)用NtCreateThread時(shí)也要提供一個(gè)用戶級(jí)的起始函數(shù),BaseProcessStart和BaseThreadStart在完成初始化時(shí)會(huì)調(diào)用這個(gè)起始函數(shù)。ETHREAD數(shù)據(jù)結(jié)構(gòu)中有兩個(gè)成份,分別用來存放這兩個(gè)地址。l設(shè)置目標(biāo)線程的KTHREAD數(shù)據(jù)結(jié)構(gòu)并為其分配堆棧。特別地,將其上下文中的斷點(diǎn)設(shè)置成指向內(nèi)核中的一段程序KiThreadStartup,使得該線程一旦被調(diào)度運(yùn)行時(shí)就從這里開始執(zhí)行。l系統(tǒng)中可能登記了一些每當(dāng)創(chuàng)建線程時(shí)就應(yīng)加以調(diào)用的通知函數(shù),調(diào)用這些函數(shù)。第四階段:通知Windows子系統(tǒng)Windows、確切地說是Windows NT、當(dāng)初的設(shè)計(jì)

24、目標(biāo)是支持三種不同系統(tǒng)的應(yīng)用軟件。第一種是Windows本身的應(yīng)用軟件,即所謂NativeWindows軟件,這是微軟開發(fā)Windows NT的真正目的。第二種是OS/2的應(yīng)用軟件,這是因?yàn)楫?dāng)時(shí)微軟與IBM還有合作關(guān)系。第三種是與Unix應(yīng)用軟件相似、符合POSIX標(biāo)準(zhǔn)的軟件,那是因?yàn)楫?dāng)時(shí)美國(guó)的軍方采購(gòu)有這樣的要求。不過實(shí)際上微軟對(duì)后兩種應(yīng)用的支持從一開始就是半心半意的,后來翅膀長(zhǎng)硬了,就更不必勉為其難了。但是,盡管如此,當(dāng)初在設(shè)計(jì)的時(shí)候還是考慮了對(duì)不同平臺(tái)的支持,即在同一個(gè)內(nèi)核的基礎(chǔ)上配以不同的外圍軟件,形成不同的應(yīng)用軟件運(yùn)行環(huán)境,微軟稱之為子系統(tǒng)(Subsystem)。于是,在Window

25、s內(nèi)核上就有了所謂Windows子系統(tǒng)、OS/2子系統(tǒng)、和POSIX子系統(tǒng)。當(dāng)然,時(shí)至今日,實(shí)際上只剩下Windows子系統(tǒng)了。那么,所謂子系統(tǒng)是怎樣構(gòu)成的呢?Internals書中闡明了Windows子系統(tǒng)的構(gòu)成,說這是由下列幾個(gè)要素構(gòu)成的。一、子系統(tǒng)進(jìn)程csrss.exe。包括了對(duì)下列成分和功能的支持:l控制臺(tái)字符型窗口的操作。面向控制臺(tái)/終端的應(yīng)用本身不支持窗口操作例如窗口的移動(dòng)、大化/小化、遮蓋等等,但是又需要在窗口中運(yùn)行,所以需要有額外的支持。l進(jìn)程和線程的管理。例如彈出一個(gè)對(duì)話窗,說某個(gè)進(jìn)程沒有響應(yīng),讓使用者選擇是否結(jié)束該進(jìn)程的運(yùn)行,等等。每個(gè)Windows進(jìn)程/線程再創(chuàng)建/退出時(shí)

26、都要向csrss.exe進(jìn)程發(fā)出通知。lDOS軟件和16位Windows軟件在(32位)Windows上的運(yùn)行。l其它。包括對(duì)當(dāng)?shù)卣Z(yǔ)言輸入法這個(gè)進(jìn)程之所以叫csrss,是C/S Run-time SubSystem的意思,csrss是Windows子系統(tǒng)的服務(wù)進(jìn)程。其實(shí)三個(gè)子系統(tǒng)都是C/S結(jié)構(gòu),但是OS/2子系統(tǒng)的服務(wù)進(jìn)程稱為os2ss,POSIX子系統(tǒng)的服務(wù)進(jìn)程稱為Psxss。之所以如此,據(jù)Internals說,是因?yàn)樽畛鯐r(shí)三個(gè)子系統(tǒng)的服務(wù)進(jìn)程是合在一起的,就叫csrss,后來才把那兩個(gè)子系統(tǒng)移了出來另立門戶,但剩下的還繼續(xù)叫csrss。二、內(nèi)核中的圖形設(shè)備驅(qū)動(dòng)、即Win32k.sys模塊。

27、其功能包括:l視窗管理,控制著窗口的顯示和各種屏幕輸出例如光標(biāo),還擔(dān)負(fù)著從鍵盤、鼠標(biāo)等設(shè)備接收輸入并將它們分發(fā)給各個(gè)具體應(yīng)用的任務(wù)。l為應(yīng)用軟件提供一個(gè)圖形函數(shù)庫(kù)。三、若干系統(tǒng)DLL,如Kernel32.dll、Advapi32.dll、User32.dll、以及Gdi32.dll。上述的第二個(gè)要素Win32k.sys原先也是和csrss.exe合在一起的,這部分功能也由服務(wù)進(jìn)程在用戶空間提供。應(yīng)用進(jìn)程通過進(jìn)程間通信向csrss發(fā)出圖形操作請(qǐng)求,由csrss完成有關(guān)的圖形操作。但是后來發(fā)現(xiàn)頻繁的進(jìn)程間通信和調(diào)度成了瓶頸,所以就把這一部分功能剝離出來,移進(jìn)了內(nèi)核,這就是Win32k.sys。這一

28、來,對(duì)于一般的32位Windows應(yīng)用而言,留給csrss、或者說必須要通過csrss辦的事就很少了。但是,盡管如此,在創(chuàng)建WIndows進(jìn)程時(shí)還是要通知csrss,因?yàn)樗鼡?dān)負(fù)著對(duì)所有WIndows進(jìn)程的管理。另一方面,csrss在接到通知以后就會(huì)在屏幕上顯示那個(gè)沙漏狀的光標(biāo),如果這是個(gè)有窗口的進(jìn)程的話。注意這里向csrss發(fā)出通知的是父進(jìn)程、即調(diào)用CreateProcess的進(jìn)程,而不是新創(chuàng)建出來的進(jìn)程,它還沒有開始運(yùn)行。至此CreateProcess的操作已經(jīng)完成,從CreateProcess返回就退出了kernel32.dll,回到了應(yīng)用程序或更高層的DLL中。這四個(gè)階段都是立足于父進(jìn)程

29、的用戶空間,在整個(gè)過程中進(jìn)行了多次系統(tǒng)調(diào)用,每次系統(tǒng)調(diào)用完成后都回到用戶空間中。例如,在第二階段中就調(diào)用了NtCreateProcess,第三階段中就調(diào)用了NtCreateThread,而整個(gè)創(chuàng)建進(jìn)程的過程包括了許多次系統(tǒng)調(diào)用有些系統(tǒng)調(diào)用屬于細(xì)節(jié),所以上面并未提及。其實(shí)Linux的進(jìn)程創(chuàng)建也不是一次系統(tǒng)調(diào)用就可完成的,典型的過程就包括fock、execve等系統(tǒng)調(diào)用,但是在Windows上就更多了。這跟Windows的整個(gè)系統(tǒng)調(diào)用界面的設(shè)計(jì)有關(guān)。以用戶空間的內(nèi)存分配為例,Linux的系統(tǒng)調(diào)用brk只有一個(gè)參數(shù),那就是區(qū)間的長(zhǎng)度,但是Windows的系統(tǒng)調(diào)用NtAllocateVirtualMe

30、mory()卻有6個(gè)參數(shù),其第一個(gè)參數(shù)是ProcessHandle,這是標(biāo)志著一個(gè)已打開進(jìn)程對(duì)象的Handle。這說明什么呢?這說明Linux進(jìn)程只能為自己分配空間,而Windows進(jìn)程卻可以為別的進(jìn)程分配空間?;蛘哒f,在存儲(chǔ)空間的分配上Linux進(jìn)程是自力更生的,而Windows進(jìn)程卻可以包辦代替。這對(duì)于系統(tǒng)設(shè)計(jì)的影響可能遠(yuǎn)超讀者的想像。就拿為子進(jìn)程的第一個(gè)線程分配用戶空間堆棧而言,既然Linux進(jìn)程線程只能為自己分配空間,而用戶空間堆棧又必須在進(jìn)入用戶空間運(yùn)行之前就已存在,那就只好在內(nèi)核中完成用戶空間堆棧的分配。相比之下,Windows進(jìn)程可以為別的進(jìn)程分配空間,于是就可以由父進(jìn)程在用戶空

31、間中為子進(jìn)程完成這些操作。這樣,有些事情L(zhǎng)inux只能在內(nèi)核中做,而Windows可以在用戶空間做。有些人稱Windows為微內(nèi)核,這或許也是個(gè)原因。而Windows的CreateProcess中包含著更多的系統(tǒng)調(diào)用,也就很好理解了?,F(xiàn)在,雖然父進(jìn)程已經(jīng)從庫(kù)函數(shù)CreateProcess中返回了,子進(jìn)程的運(yùn)行卻還未開始,它的運(yùn)行還要經(jīng)歷下面的第五和第六兩個(gè)階段。第五階段:?jiǎn)?dòng)初始線程新創(chuàng)建的線程未必是可以被立即調(diào)度運(yùn)行的,因?yàn)橛脩艨赡茉趧?chuàng)建時(shí)把標(biāo)志位CREATE_ SUSPENDED設(shè)成了1。如果那樣的話,就需要等待別的進(jìn)程通過系統(tǒng)調(diào)用恢復(fù)其運(yùn)行資格以后才可以被調(diào)度運(yùn)行。否則現(xiàn)在已經(jīng)可以被調(diào)度

32、運(yùn)行了。至于什么時(shí)候才會(huì)被調(diào)度運(yùn)行,則就要看優(yōu)先級(jí)等等條件了。而一旦受調(diào)度運(yùn)行,那就是以新建進(jìn)程的身份在運(yùn)行、與CreateProcess的調(diào)用者無關(guān)了。如前所述,當(dāng)進(jìn)程的第一個(gè)線程首次受調(diào)度運(yùn)行時(shí),由于線程系統(tǒng)空間堆棧的設(shè)置,首先執(zhí)行的是KiThreadStartup。這段程序把目標(biāo)線程的IRQL從DPC級(jí)降低到APC級(jí),然后調(diào)用內(nèi)核函數(shù)PspUserThreadStartup。最后,PspUserThreadStartup將用戶空間ntdll.dll中的函數(shù)LdrInitializeThunk作為APC函數(shù)掛入APC隊(duì)列,再企圖返回到用戶空間。Windows的APC跟Linux的signal機(jī)制頗為相似,相當(dāng)于用戶空間的中斷服務(wù)。所以,在返回用戶空間的前夕,就會(huì)檢查APC函數(shù)的存在并加以執(zhí)行如果存在的話。于是,此時(shí)的CPU將兩次進(jìn)入用戶空間。第一次是因?yàn)锳PC請(qǐng)求的存在而進(jìn)入用戶空間,執(zhí)行APC函數(shù)LdrInitializeThunk,執(zhí)行完畢以后仍回到系統(tǒng)空間。然后,第二次進(jìn)入用戶空間才是返回用戶空間。返回到用戶空間的什么地方呢?前面已經(jīng)講到,返回到Kernel32

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論