在程式設計時,某一個具體的功能模組可以通過函數或是線程等不同的形式來實現。對於同一進程而言,這些函數、線程都是存在於同一個地址空間下的,而且在執行時,大多隻對與其相關的一些資料進行處理。如果演算法存在某種錯誤,將有可能破壞與其同處一個地址空間的其他一些重要內容,這將造成比較嚴重的後果。為保護地址空間中的內容可以考慮將那些需要對地址空間中的資料進行訪問的操作部分放到另外一個進程的地址空間中運行,並且只允許其訪問原進程地址空間中的相關資料。具體的,可在進程中通過CreateProcess()函數去建立一個子進程,子進程在全部處理過程中只對父進程地址空間中的相關資料進行訪問,從而可以保護父進程地址空間中與當前子進程執行任務無關的全部資料。對於這種情況,子進程所體現出來的作用同函數和線程比較相似,可以看成是父進程在運行期間的一個過程。為此,需要由父進程來掌握子進程的啟動、執行和退出。下面這段代碼即展示了此過程:
// 臨時變數
CString sCommandLine;
char cWindowsDirectory[MAX_PATH];
char cCommandLine[MAX_PATH];
DWORD dwExitCode;
PROCESS_INFORMATION pi;
STARTUPINFO si = {sizeof(si)};
// 得到Windows目錄
GetWindowsDirectory(cWindowsDirectory, MAX_PATH);
// 啟動"記事本"程式的命令列
sCommandLine = CString(cWindowsDirectory) + "\\NotePad.exe";
::strcpy(cCommandLine, sCommandLine);
// 啟動"記事本"作為子進程
BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret) {
// 關閉子進程的主線程控制代碼
CloseHandle(pi.hThread);
// 等待子進程的退出
WaitForSingleObject(pi.hProcess, INFINITE);
// 擷取子進程的退出碼
GetExitCodeProcess(pi.hProcess, &dwExitCode);
// 關閉子進程控制代碼
CloseHandle(pi.hProcess);
}
此段代碼首先通過CreateProcess()建立Windows內建的“記事本”程式為子進程,子進程啟動後父進程通過WaitForSingleObject()函數等待其執行的結束,在子進程沒有退出前父進程是一直處於阻塞狀態的,這裡子進程的作用同單線程中的函數類似。一旦子進程退出,WaitForSingleObject()函數所等待的pi.hProcess對象將得到通知,父進程將得以繼續,如有必要可以通過GetExitCodeProcess()來擷取子進程的結束代碼。
相比而言,更多的情況是父進程在啟動完子進程後就再不與其進行任何資料交換和通訊,由其建立的子進程的執行成功與否均與父進程無關。許多大型軟體在設計時也多採用了這類思想,將某些功能完全通過獨立的應用程式來完成,當需要執行某操作時只要通過主程式啟動相應的子進程即可,具體的處理工作均由子進程去完成。這類子進程的建立過程更為簡單,例如對於上面那段代碼只需去除對子進程控制代碼pi.hProcess的等待即可:
BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret) {
// 關閉子進程的主線程控制代碼
CloseHandle(pi.hThread);
// 關閉子進程控制代碼
CloseHandle(pi.hProcess);
}
可以通過dwCreationFlags參數在建立進程時設定子進程的優先順序。前面的範例程式碼在建立子進程時使用的均是預設的優先順序,如果要將優先順序設定為高,可以修改如下:
BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, HIGH_PRIORITY_CLASS, NULL, NULL, &si, &pi);
如果在進程建立時沒有特別設定優先權,可以通過SetPriorityClass()函數來動態設定,該函數需要待操作進程的控制代碼和優先順序標識符作為入口參數,函數原型為:
BOOL SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass);
對於前面沒有設定優先順序的例子代碼,可以在子進程啟動後由父進程來動態改變其優先順序設定:
SetPriorityClass(pi.hProcess, HIGH_PRIORITY_CLASS);
或是由子進程在其啟動後自行改變優先順序設定,需要注意的是這時進程控制代碼應設定為子進程自身的控制代碼,可通過GetCurrentProcess()函數來擷取:
HANDLE hProcess = GetCurrentProcess();
SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);