如何创建一个不是其创建过程的子进程?

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() 函数?

用python多进程模块multiprocessing创建的子进程如何共享内存空间?

linux 进程 --- 进程的创建及相关api