一.内核对象句柄的继承
以这种方式共享,父子进程中使用的句柄(对于某个内核对象)的值当然是相等的。
process_A:
int main(int argc, char* argv[])
{
/*
* A进程创建一个信号量, 并将其句柄声明是可继承的。
*/
SECURITY_ATTRIBUTES security_attr;
security_attr.nLength = sizeof(security_attr);
security_attr.bInheritHandle = true;
security_attr.lpSecurityDescriptor = NULL;
HANDLE sem = ::CreateSemaphore(&security_attr, 0, 1, NULL); //创建一个未命名的信号量
cout << "sem = " << hex << sem << endl;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = true;
ZeroMemory(&pi, sizeof(si));
size_t trans_sem = reinterpret_cast<size_t>(sem);
char commandLine[32] = { 0 };
sprintf_s(commandLine, "%u", trans_sem);
/*
* A进程创建子进程B,并声明B可以继承父进程中可继承的句柄,
* B进程被创建的同时,会将A进程中可继承的句柄复制到B进程的句柄表中,
* A通过命令行传递可继承句柄值给B
*/
bool rlt = ::CreateProcess("E:\\MYVC\\test\\Debug\\process_B.exe",
commandLine, NULL, NULL, true,
CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (rlt)
{
cout << "create process success." << endl;
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
}
size_t cnt = 5;
while (cnt)
{
cout << cnt-- << endl;
Sleep(1000);
}
cout << "release sem." << endl;
::ReleaseSemaphore(sem, 1, NULL);
::CloseHandle(sem);
getchar();
return 0;
}
process_B:
int main(int argc, char* argv[])
{
cout << "commandLine :" << endl;
cout << "\targc = " << argc << endl;
cout << "\targv[0] = " << argv[0] << endl;
size_t tmp = atoi(argv[0]);
HANDLE sem = reinterpret_cast<HANDLE>(tmp);
cout << "sem = " << hex << sem << endl;
::WaitForSingleObject(sem, INFINITE);
::CloseHandle(sem);
cout << "get sem response" << endl;
getchar();
return 1;
}
二. 打开命名内核对象
以这种方式共享,如果子进程继承了父进程的句柄,那么在子进程中打开命名内核对象返回的句柄值,与父进程中该命名内核对象的句柄值是不相等的;如果子进程没有继承父进程的句柄,则相等。
process_A:
同上, 只是当创建子进程B的时候,可以不继承A进程的句柄, 或者不将A进程中的句柄声明是可继承的。
process_B:
int main(int argc, char* argv[])
{
char *pName = "TEST";
WCHAR wcName[32];
memset(wcName, 0, sizeof(wcName));
MultiByteToWideChar(CP_ACP, 0, pName, strlen(pName) + 1, wcName,
sizeof(wcName) / sizeof(wcName[0]));
HANDLE sem = ::OpenSemaphore(SEMAPHORE_ALL_ACCESS, false, wcName); //打开"TEST"命名内核对象
cout << "sem = " << hex << sem << endl;
::WaitForSingleObject(sem, INFINITE);
::CloseHandle(sem);
printf("get sem response.\n");
getchar();
}
三. 复制内核对象句柄
以这种方式共享,复制出来的句柄值与原句柄值相等。
process_A:
HANDLE getProcessHandle(const char* pProcessName)
{
::PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
//给系统所有进程拍一个快照
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot error.\n");
return NULL;
}
BOOL bFind = false;
//遍历所有快照,查找指定名字的线程
BOOL bMore = ::Process32First(hProcessSnap, &pe32);
while (bMore)
{
//printf("进程名称:%s\n", pe32.szExeFile);
//printf("进程ID号: %u\n\n", pe32.th32ProcessID);
if (0 == strcmp(pe32.szExeFile, pProcessName))
{
bFind = true;
break;
}
else
{
bMore = ::Process32Next(hProcessSnap, &pe32);
}
}
::CloseHandle(hProcessSnap);//释放进程快照
if (!bFind)
{
return NULL;
}
HANDLE hDstProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS, false, pe32.th32ProcessID);
return hDstProcessHandle;
}
int main(int argc, char* argv[])
{
HANDLE sem = ::CreateSemaphore(NULL, 0, 1, NULL);
cout << "sem = " << hex << sem << endl;
//主动将本进程的内核对象句柄sem复制到目标进程
HANDLE hDstProcessHandle;
HANDLE hNewHandle;
hDstProcessHandle = getProcessHandle("process_B.exe"); //process_B首先得运行
BOOL bRet = ::DuplicateHandle(GetCurrentProcess(), sem, hDstProcessHandle, &hNewHandle,
0, false, DUPLICATE_SAME_ACCESS);
/*
* 注意!!!在这里,必须想办法通知子进程process_B该新句柄的值,这里为了测试方便,故直接
* 打印该句柄的值,在process_B中输入该值,从而直接使用
*/
cout << "newHandle : " << hNewHandle << endl;
size_t cnt = 10;
while (cnt)
{
cout << cnt-- << endl;
Sleep(1000);
}
cout << "release sem." << endl;
::ReleaseSemaphore(sem, 1, NULL);
::CloseHandle(sem);
getchar();
return 0;
}
process_B:
int main(int argc, char* argv[])
{
HANDLE sem;
cout << "input newHandle: " << endl;
cin >> sem; //注意这里输入为16进制整数
::WaitForSingleObject(sem, INFINITE);
::CloseHandle(sem);
printf("get sem response.\n");
getchar();
getchar();
}