1. 程式人生 > >Windows內核之進程的終止和子進程

Windows內核之進程的終止和子進程

exitcode hand 返回 bsp 全部 views 地址空間 col data-

1 進程終止的方法:

<1>主線程的進入點函數返回(最好使用這種方法)

<2>進程中的一個線程調用ExitProcesss函數(應該避免使用這樣的方法)。

<3>還有一個進程中的線程調用TerminateProcess函數(應該避免使用這樣的方法)。

<4>進程中的全部線程自行終止執行(這樣的情況差點兒從未發生)。

1.1 主線程進入點函數返回

始終都應該這樣來設計應用程序。即僅僅有當主線程的進入點函數返回時,它的進程才終止執行。這是保證全部線程資源可以得到正確清除的唯一辦法。

<1> C++對象將可以使用它們的析構函數得以釋放

<2> 操作系統可以正確的釋放該線程使用的堆棧內存

<3> 系統將進程的退出代碼設置為進入點函數的返回值

<4> 系統將內核對象的計數值減去1

1.2 調用ExitProcess函數

voidExitProcess(uExitCode)

跟主線程的進入點函數返回相比,它就不那麽安全,不能保證資源被清理。

通過調用ExitProcess函數。C++/C執行期啟動代碼可以確保主線程從它的進入點函數返回時,進程便終止執行,而無論進程中是否還有其它線程在執行。

假設在進入點函數中調用ExitThread。那麽主線程就會停止執行,可是假設進程中假設還有其它線程的話。進程便不會終止。

ExitProcess以及ExitThread能保證操作系統資源在函數調用時被清除,可是不能保證C/C++執行時資源被正確的清除。所以不妨不要調用這些資源。

在前面也介紹過當主線程的進入點函數返回的時候。C/C++執行時會調用執行時的exit函數。exit函數會完畢以下操作

<1>調用_onexit函數的調用而註冊的人不論什麽函數

<2>為全部的全局和靜態的C++對象調用析構函數

<3>調用系統的ExitProcess函數。將nMainRetVal傳遞給它。

使得操作系統可以撤銷進程並設置它的exit代碼。

1.3 調用TerminateProcess 函數

BOOL TerminateProcess(HANDLE hProcess,UINTnExitCode)

這個函數通知進程內全部線程終止。當全部線程終止時。進程也會終止了,可是它不會告訴進程內相關聯的DLL這個進程將要被終止。它做的事情:

<1>全部打開的句柄被關閉

<2>全部的線程會被終止

<3>進程對象的狀態變為終止的,滿足全部等待進程結束的線程

<4>進程中全部線程對象的狀態變為終止。滿足全部等待線程結束的線程

<5>進程的終止狀態由STILL_ACTIVE變為了進程的返回代碼

這個函數是異步的。它告訴操作系統,你要終止某個進程。可是當函數返回的時候,你無法保證進程是否已經被殺死。假設想要確切知道進程是否被殺死,能夠使用WaitForSingleObject函數。

2 進程終止時的情況

<1>進程中全部剩余線程將被終止

<2>進程中指定的用戶對象,GDI對象被釋放。內核對象被關閉

<3>內核對象的狀態編程收到通知的狀態

<4>進程的退出代碼由STILL_ACTIVE 變為ExitProcess或者TerminateProcess傳遞的的退出代碼

<5>進程內核對象計數減去1

能夠通過函數 BOOLGetExitCodeProcess(HANDLE handle,LPDWORD lpExitCode)來查找進程的退出代碼。假設代碼是STILL_ACTIVE表示的是進程還沒終止。假設不是這個,就說明進程已經被終止。

3 子進程

程序中要實現一段功能一共同擁有3種方法:

<1>調用函數

<2>開辟新線程

<3>開辟新進程

3.1 調用函數

調用函數時很常見的。可是它的缺點是由於在同一個線程中,所以必須等待此函數運行完成,才幹運行後面的代碼

3.2 開辟新線程

這樣可以在新線程運行的時候,同一時候運行其它線程的代碼,可是這種缺點是不同線程之間須要交流數據時候。會產生同步的問題。

3.3 開辟子進程

這樣有點是既能夠保護數據。能夠同步運行,也能夠等待新進程運行完成再去運行其它進程的代碼。缺點是開辟新進程,會造成地址空間的浪費。

Windows內核之進程的終止和子進程