首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

VC++ 進程與多進程管理核心技術詳解

     編輯:關於VC++

前言:進程基本概念

進程是作業系統中載入記憶體、正在執行的應用程式實例。每個進程包含核心物件(供系統管理統計資訊)與位址空間(含程式碼、資料、執行緒堆疊、堆積配置等動態空間)。進程本身無法執行操作,必須擁有至少一個執行緒(主執行緒)在其位址空間內執行程式碼。主執行緒結束即意味著進程終止,系統會自動釋放其位址空間。

每個載入進程的可執行檔或 DLL 映像會獲得唯一的實例控制碼 HINSTANCE,實際上記錄該模組在進程中的基底記憶體位址。VC++ 連結器產生的程式預設基底位址為 0x00400000,通常無需修改。可透過 GetModuleHandle() 取得指定模組的基底位址。


一、子進程建立與管理

CreateProcess 完整流程

CreateProcess() 會建立新進程核心物件(參考計數初始為 1)、配置虛擬位址空間、載入可執行檔與必要 DLL、建立主執行緒核心物件並啟動 WinMain() 入口函式。

函式原型與關鍵參數

BOOL CreateProcess(
    LPCTSTR lpApplicationName,        // 可執行模組名稱
    LPTSTR lpCommandLine,             // 命令列字串
    LPSECURITY_ATTRIBUTES lpProcessAttributes,  // 進程安全屬性
    LPSECURITY_ATTRIBUTES lpThreadAttributes,   // 執行緒安全屬性
    BOOL bInheritHandles,             // 控制碼繼承旗標
    DWORD dwCreationFlags,            // 建立旗標(可設優先權)
    LPVOID lpEnvironment,             // 環境區塊指標
    LPCTSTR lpCurrentDirectory,       // 目前目錄
    LPSTARTUPINFO lpStartupInfo,      // 啟動資訊結構
    LPPROCESS_INFORMATION lpProcessInformation // 進程資訊結構
);

同步等待模式:父進程阻塞直到子進程結束

CString sCmdLine;
char cWinDir[MAX_PATH], cCmdLine[MAX_PATH];
DWORD dwExitCode;
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };

GetWindowsDirectory(cWinDir, MAX_PATH);
sCmdLine = CString(cWinDir) + _T("\\Notepad.exe");
_tcscpy(cCmdLine, sCmdLine);

BOOL ret = CreateProcess(NULL, cCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret) {
    CloseHandle(pi.hThread);                    // 關閉主執行緒控制碼
    WaitForSingleObject(pi.hProcess, INFINITE); // 等待子進程結束
    GetExitCodeProcess(pi.hProcess, &dwExitCode); // 取得結束代碼
    CloseHandle(pi.hProcess);                   // 關閉進程控制碼
}

此模式下子進程如同同步函式呼叫,父進程在 WaitForSingleObject 處阻塞,子進程結束後繼續執行。

非同步啟動模式:啟動後不再關心子進程

BOOL ret = CreateProcess(NULL, cCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret) {
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);  // 立即關閉控制碼,不等待
}

適用於獨立功能模組,大型軟體常採用此架構將功能拆分為獨立執行檔。

進程優先權控制

  • 建立時指定:dwCreationFlags 設為 HIGH_PRIORITY_CLASS 等常數
  • 動態調整(父進程):SetPriorityClass(pi.hProcess, HIGH_PRIORITY_CLASS);
  • 動態調整(子進程自身):SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

二、進程互斥執行(單一實例保護)

某些程式(如獨佔序列埠)要求系統中僅存在一個實例。核心邏輯:啟動時檢查是否已有實例,若有則退出。

方法一:具名互斥量

HANDLE hMutex = CreateMutex(NULL, FALSE, _T("MyUniqueAppName"));
if (GetLastError() == ERROR_ALREADY_EXISTS) {
    CloseHandle(hMutex);
    return FALSE;  // 已有實例,終止啟動
}

CreateMutex 若發現同名互斥量已存在,會傳回既有控制碼並設定錯誤碼 ERROR_ALREADY_EXISTS,以此實現單一實例檢查。

方法二:全域共享變數(MFC 專用)

#pragma data_seg("Shared")
volatile long g_lAppInstance = 0;
#pragma data_seg()
#pragma comment(linker, "/section:Shared,RWS")

// 在 InitInstance 開頭:
if (++g_lAppInstance > 1)
    return FALSE;

利用編譯器指令建立跨進程共享資料區,所有進程實例共用同一變數計數器。

關鍵點: 以上程式碼必須放在 CWinApp::InitInstance() 最開頭,確保在任何視窗建立前完成檢查。

三、進程終止方式比較

函式適用範圍特性風險
ExitProcess(uExitCode)本進程正常終止,通知 DLL、清理執行緒資源強制性強,後續程式碼不執行,若有 new 未 delete 會記憶體洩漏
TerminateProcess(hProcess, uExitCode)任意進程(需控制碼)非同步、強制終止,不通知被終止進程極度危險,無法執行清理程式碼,僅作最後手段

若呼叫 TerminateProcess 後需確認進程確實結束,可搭配 WaitForSingleObject(hProcess, INFINITE) 等待。


小結

多進程管理是多工程式設計的核心。本文詳細說明子進程建立與同步/非同步模式、優先權控制、單一實例互斥機制(具名互斥量與共享變數兩種做法)、以及進程終止的正常與強制方式。掌握這些技術可構建穩健、模組化的 Windows 應用程式架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved