進程(Process)是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,是系統進行資源分配和調度的一個獨立單位。程序只是一組指令的有序集合,它本身沒有任何運行的含義,只是一個靜態實體。而進程則不同,它是程序在某個數據集上的執行,是一個動態實體。它因創建而產生,因調度而運行,因等待資源或事件而被處于等待狀態,因完成任務而被撤消,反映了一個程序在一定的數據集上運行的全部動態過程。
線程(Thread)是進程的一個實體,是CPU調度和分派的基本單位。線程不能夠獨立執行,必須依存在進程中,由進程提供多個線程執行控制。從內核角度講線程是活動體對象,而進程只是一組靜態的對象集,進程必須至少擁有一個活動線程才能維持運轉。當某個應用程序調用一個創建進程的函數比如CreateProcess或者用戶執行某一個程序(其實windows下用戶執行一般普通程序是由explorer.exe調用CreateProcess來完成),操作系統把這個過程分成以下步驟來完成:
1.打開將要在該進程中執行的映像文件。
2.創建Windows執行體進程對象。
3.創建初始線程(棧、堆執行環境初始化及執行線程體對象)。
4.通知Windows子系統新進程創建了(子系統是操作系統的一部分它是一個協助操作系統內核管理用戶態/客戶方的一個子系統具體的進程為Csrss.exe)。
5.開始執行初始線程(如果創建時候指定了線程的CREATE_SUSPENDED狀態則線程暫時掛起不執行)。
6.在新進程和線程環境中完成地址空間的初始化(比如加載必須的DLL和庫),然后開始到進程入口執行。
到這里操作系統完成一個新進程的創建過程。
下面來看下具體每一步操作系統所做的工作:
1.打開將要在該進程中執行的映像文件。
首先操作系統找到執行的Windows映像然后創建一個內存區對象,以便后面將它映射到新的進程地址空間中。
2.創建Windows執行體進程對象。
接下來操作系統調用內部的系統函數NtCreateProcess來創建一個Windwos執行體進程對象。具體步驟是:
(1)建立EPROCESS
*分配并初始化EPROCESS結構塊
*從父進程處繼承得到進程的親和性掩碼
*分配進程的最大最小工作集尺(由兩個參數決定PsMinimumWorkingSet PsMaximumWorkingSet)
*降新進程的配額塊設置為父進程配額塊地址,并遞增父進程配額塊的引用計數
*繼承Windows的設備名字空間
*將父進程進程ID保存在新進程對象的InheritedFormUniqueProcessId中
*創建該進程的主訪問令牌
*初始化進程句柄表
*將新進程的退出狀態設置為STATUS_PENDING
(2)創建初始的進程地址空間
*在適當的頁表中創建頁表項,以映射初始頁面
*從MmresidentAvailablePage算出進程工作集大小
*系統空間的非換頁部分和系統緩存的頁表被映射到進程
(3)初始化內核進程塊KPROCESS
(4)結束進程地址空間的創建過程
(5)建立PEB
(6)完成執行體進程對象的創建過程
3.創建初始線程(棧、堆執行環境初始化及執行線程體對象)。
這時候Windows執行體進程對象已經完全建立完成,但它還沒有線程所以無法執行,
接下來系統調用NtCreateThread來創建一個掛起的新線程它就是進程的主線程體。
4.通知Windows子系統新進程創建了(子系統是操作系統的一部分它是一個協助操作系統內核管理用戶態/客戶方的一個子系統具體的進程為Csrss.exe)。
接下來操作系統通過客戶態(Kernel32.dll)給Windows子系統(Csrss)發送一個新進程線程創建的數據消息,讓子系統建立自己的進程線程管理塊。當Csrss接收到該消息時候執行下面的處理:
*復制一份該進程和線程句柄
*設置進程優先級
*分配Csrss進程塊
*把新進程的異常處理端口綁定到Csrss中,這樣當該進程發生異常時,Csrss將會接收到異常消息
*分配和初始化Csrss線程塊
*把線程插入到進程的線程列表中
*把進程插入到Csrss的線程列表中
*顯示進程啟動光標
5.開始執行初始線程(如果創建時候指定了線程的CREATE_SUSPENDED狀態則線程暫時掛起不執行)。到這里進程環境已經建立完畢進程中開始創建的主線程到這里獲得執行權開始執行線程
6.在新進程和線程環境中完成地址空間的初始化(比如加載必須的DLL和庫),然后開始到進程入口執行。到這步實質是調用ldrInitializeThunk來初始化加載器,堆管理器NLS表TLS數組以及臨界區結構,并且加載任何必須要DLL并且用DLL_PROCESS_ATTACH功能代碼來調用各DLL入口點,最后當加載器初始化例程返回到用戶模式APC分發器時進程映像開始在用戶模式下執行,然后它調用線程啟動函數開始執行。
到這里操作系統完成了所有的創建工作,我們寫的程序就這樣被操作系統調用運行起來了。