我目前是通过命令行将pid传递给子进程,但是在Win32 API中有没有一种方法可以做到这一点?另外,是否有人可以消除我担心的疑虑,即如果父进程死亡后,我传递的pid可能属于另一个进程?
提供一份代码示例,以便其他人在查找此问题时可以参考。最近我正在开发一个Python库项目,不久前也需要做到这一点。以下是我编写的测试/样本代码:
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>
int main(int argc, char *argv[])
{
int pid = -1;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
//assume first arg is the PID to get the PPID for, or use own PID
if (argc > 1) {
pid = atoi(argv[1]);
} else {
pid = GetCurrentProcessId();
}
if( Process32First(h, &pe)) {
do {
if (pe.th32ProcessID == pid) {
printf("PID: %i; PPID: %i\n", pid, pe.th32ParentProcessID);
}
} while( Process32Next(h, &pe));
}
CloseHandle(h);
}
if ( h == INVALID_HANDLE_VALUE ) { // got an invalid handle
- hmatt1更好的方法是调用DuplicateHandle()
函数来创建一个可继承的进程句柄副本,然后创建子进程并将句柄值传递给命令行。在父进程中关闭复制的句柄。
当子进程完成时,它也需要Close
其副本。
ULONG_PTR GetParentProcessId() // By Napalm @ NetCore2K
{
ULONG_PTR pbi[6];
ULONG ulSize = 0;
LONG (WINAPI *NtQueryInformationProcess)(HANDLE ProcessHandle, ULONG ProcessInformationClass,
PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
*(FARPROC *)&NtQueryInformationProcess =
GetProcAddress(LoadLibraryA("NTDLL.DLL"), "NtQueryInformationProcess");
if(NtQueryInformationProcess){
if(NtQueryInformationProcess(GetCurrentProcess(), 0,
&pbi, sizeof(pbi), &ulSize) >= 0 && ulSize == sizeof(pbi))
return pbi[5];
}
return (ULONG_PTR)-1;
}
NtQueryInformationProcess
返回0xC0000024或0xC0000008的情况。 - Oliver Bock注意,如果父进程终止,很可能甚至有可能会重新使用PID分配给另一个进程。这是标准的Windows操作。
因此为了确保,一旦您接收到父进程的ID并确认它确实是您的父进程,应该打开一个句柄并使用它。
请问有没有其他方法可以缓解我的担忧?如果父进程已经死亡,我传递的pid是否可能在某些时间属于另一个进程?
是的,PID可以被重用。与UNIX不同,Windows没有维护强大的父子关系树。