調用 CreateProcess 創建進程時,可以讓子進程繼承父進程句柄表中可以被繼承的內核對象。
一個內核對象能夠被繼承,必須在創建時通過 SECURITY_ATTRIBUTES 結構指定可繼承;另一個條件是 CreateProcess 第五個參數 bInheritHandles 必須設置爲 TRUE.
下面通過一個例子演示句柄繼承。
創建兩個控制檯程序扮演父進程和子進程,其中,內核對象使用事件來舉例,使用了命令行參數傳遞事件句柄。子進程啓動後,獲取命令行參數,得到事件句柄,這樣就完成了內核對象的繼承,本質上是把父進程句柄表中的事件複製到子進程的句柄表中。
父進程中,在 SetEvent 調用處設置斷點,以便觀察。
父進程
// ParentProcess.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WINDOWS.H>
int main(int argc, char* argv[])
{
char szBuffer[256] = {0};
// 創建可繼承內核對象必須在 SECURITY_ATTRIBUTES 中指定可繼承
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// 創建可繼承的內核對象
HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, NULL);
sprintf(szBuffer, "c:\\SubProcess.exe %x", hEvent);
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
CreateProcess(NULL, szBuffer, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
// 設置事件爲已通知
SetEvent(hEvent);
// 關閉句柄,內核對象不會銷燬,因爲子進程已經獲取了該句柄
CloseHandle(hEvent);
return 0;
}
子進程
// SubProcess.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WINDOWS.H>
#include <TCHAR.H>
int main(int argc, char* argv[])
{
char szBuffer[256] = {0};
memcpy(szBuffer, argv[1], strlen(argv[1]));
DWORD dwHandle = 0;
sscanf(szBuffer, "%x", &dwHandle);
printf("%s\n", argv[0]);
printf("%x\n", dwHandle);
HANDLE hEvent = (HANDLE)dwHandle;
printf("開始等待事件通知...\n");
WaitForSingleObject(hEvent, INFINITE);
DWORD dwCode = GetLastError();
printf("事件已通知.\n");
getchar();
return 0;
}
運行結果
子線程以創建,並在 WaitForSingleObject 處阻塞,當父進程繼續執行 SetEvent ,則事件對象設置爲已通知,子進程 WaitForSingleObject 執行完成。