1. 進程概念
進程是一個運行程序的實例。
包含2個東東:
一個讓操作系統管理進程的內核對象。
一個地址空間(包含執行代碼和數據),也包含動態內存分配的空間。
一個進程必須靠線程運行,它至少含有一個線程,即主線程。主線程再來創建更多線程。
2. 進程啓動
Windows有一個啓動函數 "XXmianCRTStartup",根據程序類型不同啓動函數有所區別。
啓動函數會調用代碼中的"XXmain"入口函數。通過鏈接指令"/SUBSYSTEM:
"可以修改程序類型和入口函數。
命令行
獲取命令行參數
//main.cpp
#include <stdio.h>
#include <Windows.h>
int main(int argc,char **argv)
{
PTSTR pstr=GetCommandLine();
wprintf(L"%s\n",pstr);
return 0;
}
其它
還可以獲取環境變量、工作目錄、操作系統版本等。
2.1. 創建進程
一個進程可以創建其它進程,需要知道程序文件名稱和位置即可。創建進程可以設置諸多參數,比如命令行參數、控制檯窗口、窗口大小位置等,非常靈活。
用這種技術非常容易實現一個集成工具,調用其它工具完成子任務。結合控制檯輸出重定向技術,還能顯示創建進程的控制檯輸出內容。典型的應用是集成型的Studio類工具,調用各種compiler編譯程序,並且輸出編譯錯誤和提示信息。
2.2. 結束進程
進程結束有四種方式。
2.2.1.1. 主線程結束
主線程執行結束,調用"return"返回,進程就會退出,這是正常退出方式。主線程退出後,是不管其它子線程的狀態,操作系統會把它們強制結束掉。
2.2.1.2. 調用ExitProcess
當程序主線程return返回的時候,啓動接口函數("XXstartup")會調用ExitProcess退出進程。因此即使這個時候還有其它子線程沒有結束,這個時候也會結束掉。
如果顯示調用ExitProcess,進程會直接退出,操作系統能保證所有資源能夠得到釋放。但是這麼做要儘量避免,因爲很多退出函數,特別是析構函數是不會執行的。如果需要在退出的時候進行其他工作,那麼就不能用這種方式退出。
進程結束的前提條件是所有線程都結束。因此,如果在主線程中顯示調用ExitThread,那麼子線程不結束,進程也不會結束。書中說會造成資源泄漏,我想是不是因爲子線程可能永遠都不結束,它們佔有的資源永遠不會釋放掉。
2.2.1.3. 調用TerminateProcess
和ExitPrecess的區別是這個函數可以結束其它進程。
其它和前者類似。
2.2.1.4. 當進程終止
所有線程會被終止。
用戶對象、GDI對象會釋放,內核對象會關閉(因此不用擔心鎖之類的東西沒有釋放,導致死鎖)。
The process kernel object's status becomes signaled.這非常有用,例如其它進程可以通過WaitForSingleObject等待該進程結束後執行某段代碼。
進程結束後,進程內核對象引用計數減一,但是不一定會被釋放。如果父進程還有打開的子進程句柄,父進程是可以繼續訪問子進程內核對象,獲取一些信息,例如獲取"ExitCode"。
2.3. 子進程
創建一個進程,並等待它結束。
PROCESS_INFORMATION pi;
DWORD dwExitCode;
// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) {
// Close the thread handle as soon as it is no longer needed!
CloseHandle(pi.hThread);
// Suspend our execution until the child has terminated.
WaitForSingleObject(pi.hProcess, INFINITE);
// The child process terminated; get its exit code.
GetExitCodeProcess(pi.hProcess, &dwExitCode);
// Close the process handle as soon as it is no longer needed.
CloseHandle(pi.hProcess);
}
如果創建一個進程不需要等待它,那麼可以創建成功後立刻關閉線程句柄和進程句柄。
PROCESS_INFORMATION pi;
// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) {
// Allow the system to destroy the process & thread kernel
// objects as soon as the child process terminates.
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}