WINDOWS的任務管理器打開會有很多的進程,有些是WINDOWS系統的,有些是我們運行的軟件,
WINDOWS支持兩種類型的應用程序,GUI和CUI,也就是圖形用戶界面Graphical User Interface)和
控制台用戶界面Console User Interface),我們所使用的程序一般都是GUI的,CMD.EXE是典型的
CUI程序,這種東西很少了,想想也知道,沒有界面交互,用戶用了不爽!
應用程序必須有一個入口點函數,我們在創建程序的時候VS會幫我們自動判斷我們創建的程序應
該為哪一個子系統,在連接器的/SUBSYSTEM裡可以人為的設置這個連接器開關,其實也就是強制的選
擇一個入口點函數。根據程序所使用的字符集,應用程序的類型的不同,主要有以下四種入口點函
數,這裡就借用WINDOWS核心編程這本書的圖片吧。
有人可能會奇怪,後面怎麼還有啟動函數,實際上入口函數不是程序執行的開始,在入口點函數之前
還有一個被稱為啟動函數的函數,這個啟動函數的作用是為程序的開始運行做一些初始化的准備工作。
下面說下如何創建一個進程,一般來講,我們編寫的程序都是單一進程的,但是也有一些程序用到了很多進程,也就是在進程裡創建進程。創建進程的函數式這樣的:
BOOL CreateProcess( LPCWSTR pszImageName, LPCWSTR pszCmdLine, LPSECURITY_ATTRIBUTES psaProcess, LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles, DWORD fdwCreate, LPVOID pvEnvironment, LPWSTR pszCurDir, LPSTARTUPINFOW psiStartInfo, LPPROCESS_INFORMATION pProcInfo );
一個線程調用CreateProcess時,系統將創建一個進程內核對象,其初始化使用計數為1。進程
內核對象不是進程本身,而是操作系統用來管理這個進程的一個小型數據結構。然後,系統為新進程
創建一個虛地址空間,並將可執行文件和所有必要的DLL)的代碼及數據加載到進程的地址空間。
然後,系統為新進程的主線程創建一個線程內核對象其使用計數為1)。和進程內核對象一樣,
線程內核對象也是一個小型數據結構,操作系統用它來管理這個線程。這個主線程一開始就會執行
C/C++運行時的啟動函數,也就是剛才說的一些列的CRT字樣的啟動函數,最終會調用應用程序的入口
函數,也就是一系列帶main,WinMain字樣的函數,這裡寫的東西才是我們真正的程序員寫的東西。
要說明的是,CreateProcess在進程完全初始化好之前就返回TRUE,這意味著系統尚未嘗試定位
所有必要的DLL,如果一個DLL找不到,或者不能正確的初始化,進程就會終止。所以父進程不會注意
到任何初始化問題,下面對這個CreateProcess函數的參數進行一下說明。
pszImageName 新進程要使用的可執行文件的名稱
pszCmdLine 傳給新進程的命令行字符串
psaProcess 該結構為進程制定安全說明符,一般為NULL,默認的安全描述符,也就是不可以繼承。
psaThread 該結構為進程的主線程制定安全說明符。
fInheritHandles 設置為true指示調用進程中的每個可繼承句柄都由已啟動的進程繼承,設置為
false指示不繼承這些句柄
fdwCreate win32進程創建標志)的按位組合,這些標志控制已啟動的進程的優先級數和行為。
pvEnvironment 指向新進程的環境塊的指針。
pszCurDir 指向NULL結尾的字符串的指針,該字符串制定進程當前目錄的完整路徑。為NULL,則新進程具有相同的當前驅動器和目錄。
psiStartInfo 指向WIN32 STARTUPINFOW 結構的指針,該結構為已啟動的進程的主窗口指定窗口站、桌面、標准句柄和外觀。
pProcInfo 指向WIN32 PROCESS_INFORMATION 結構的指針,該結構指定有關要啟動的進程的表示信息。
進程可以通過以下四種方式終止:
1 主線程的入口點函數返回
2 進程中的一個線程調用ExitProcess函數
3 另一個進程中的線程調用TerminateProcess函數
4 進程中的所有線程都“自然死亡"
第一種方式是最好的,可以保證該線程創建的任何C++對象都有這些對象的析構函數正確銷毀,操作系
統將正確釋放線程棧使用的內存,系統將進程的退出代碼設為入口點函數的返回值,系統遞減進程內
核對象的使用計數。
用ExitProcess終止進程,退出代碼被設置為fuExitCode,當主線程的入口點函數返回時,會返回到
C/C++運行庫的啟動代碼,後者將正確清理進程使用的全部C運行時的資源。釋放了C運行時資源之
後,C運行時啟動代碼將顯示調用ExitProcess,並將入口點函數返回的值傳給它。ExitProcess造
成進程“當場終止運行”:C/C++運行時沒有機會執行清理操作。在主線程中應避免使用
ExitProcess,任何時候都不要顯示調用ExitProcess只要確保主線程的入口點函數返回,C/C++運
行時就能執行清理工作。
TerminateProcess被終止自己的進程也可以終止另外一個進程,但是應用程序不能正確清理,雖然
進程沒有機會執行自己的清理工作,但是操作系統會在進程終止後徹底進行清理,確保不會洩露任何
操作系統。進程在終止後絕對不會洩露任何東西,這是操作系統幫我們清理了。當一個進程中的所有
線程都結束了,不管是怎麼結束的,一旦系統檢測到一個進程中沒有任何線程在運行,就會終止這個
進程,進程的退出代碼會被設置為最後一個終止的那個線程的退出代碼。
當一個進程終止時,系統會依次執行以下操作:
1. 終止進程中遺留的任何線程。
2. 釋放進程分配的所有用戶對象的GDI對象,關閉所有內核對象在其它進程中打開的內核對象除外)
3. 進程的退出代碼從STILL_ACTIVE變為ExitProcess或TerminateProcess函數的代碼
4. 進程內核對象的狀態變為已觸發狀態
5. 進程內核對象的使用計數-1.
本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1297643