如何创建一个不是其创建过程的子进程?
Posted
技术标签:
【中文标题】如何创建一个不是其创建过程的子进程?【英文标题】:How to create a process that is not a child of it's creating process? 【发布时间】:2010-06-28 21:11:39 【问题描述】:我有两个进程,A 和 B。在某个时刻 A 创建 B。在创建 B 之后,如果 A 的进程 tree 被杀死,我希望 B 仍然存在。
我正在使用 CreateProcess() 来创建 B,但我似乎无法找到任何方法让它在没有孩子的情况下创建进程。与 ShellExecuteEx() 相同,但我可能缺少一些标志。
有谁知道我可以用什么来做到这一点?
编辑:我忘了提到两个进程都需要一个 HANDLE 或另一个进程 ID
【问题讨论】:
您是否查看了 CreateProcess() 的创建标志参数中的 CREATE_NEW_PROCESS_GROUP? 【参考方案1】:你可以尝试进程A创建进程C,创建进程B然后进程C会立即结束(终止)。在进程 B 中,仅存在有关直接父进程(C 的进程 ID,未运行)的信息,而不是有关进程 A 的信息。因此,“如果 A 的进程树被杀死”,则进程 B 可能会继续运行。
例如,您启动 Process Explorer(参见 http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx)然后启动 Total Commander。从 Total Commander 启动 cmd.exe。从 cmd.exe 启动 notepad.exe。然后在 cmd.exe 中键入“exit”。 cmd.exe 终止后,您可以看到notepad.exe 将不再显示在Total Commander (totalcmd.exe) 下。在 Process Explorer 中为 Total Commander (totalcmd.exe) 选择“Kill Process Tree”后,您可以看到 notepad.exe 仍在运行。
【讨论】:
好的,我试过了,我认为它会做,我忘记的一件事是两个进程都需要彼此的进程 ID。使用此解决方案,进程 B 将具有进程 A 的 ID,但 A 将只有 B。我想我可以通过某种消息传递来解决这个问题。谢谢! 每个进程都可以设置退出代码(关于ExitProcess
或C函数exit
)。因此,如果进程 C(中间进程)作为退出代码返回进程 B 的进程 ID,则进程 A 可以给出它,例如关于 GetExitCodeProcess
函数。
是的,我想这就是我要做的,这似乎有点老套,但至少现在已经足够了【参考方案2】:
您可以在 createprocess API 中将参数 dwcreationflags 设置为 DETACHED_PROCESS。
【讨论】:
DETACHED_PROCESS 与父子进程链无关。启用该标志后,子进程将不会收到任何控制台,因此子进程不会与其父进程共享控制台,这与 CreateProcess() 的默认行为相反。【参考方案3】:调用kernel32!CreateProcess()
时,您可以使用进程属性指定不同的父级。这是一个可以做到这一点的函数。
bool CreateProcessWithParent(DWORD parentId, PWSTR commandline)
auto hProcess = ::OpenProcess(PROCESS_CREATE_PROCESS, FALSE, parentId);
if (!hProcess)
return false;
SIZE_T size;
//
// call InitializeProcThreadAttributeList twice
// first, get required size
//
::InitializeProcThreadAttributeList(nullptr, 1, 0, &size);
//
// now allocate a buffer with the required size and call again
//
auto buffer = std::make_unique<BYTE[]>(size);
auto attributes = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(buffer.get());
::InitializeProcThreadAttributeList(attributes, 1, 0, &size);
//
// add the parent attribute
//
::UpdateProcThreadAttribute(attributes, 0,
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
&hProcess, sizeof(hProcess), nullptr, nullptr);
STARTUPINFOEX si = sizeof(si) ;
//
// set the attribute list
//
si.lpAttributeList = attributes;
PROCESS_INFORMATION pi;
//
// create the process
//
BOOL created = ::CreateProcess(nullptr, commandline, nullptr, nullptr,
FALSE, EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr,
(STARTUPINFO*)&si, &pi);
//
// cleanup
//
::CloseHandle(hProcess);
::DeleteProcThreadAttributeList(attributes);
return created;
源码取自https://scorpiosoftware.net/2021/01/10/parent-process-vs-creator-process/
【讨论】:
以上是关于如何创建一个不是其创建过程的子进程?的主要内容,如果未能解决你的问题,请参考以下文章
当父进程被杀死时,使用 fork() 创建的子进程是不是会自动被杀死?
如何重定向 fork() 创建的子进程的 IO 并使用 exec() 函数?