我可以在Python中创建一个子进程并像这样挂起它:
proc = subprocess.pOpen(['binary', 'arg1', 'arg2'])
# Subprocess was created in a running state
proc_handle = psutil.Process(pid=proc.pid)
proc_handle.suspend()
# Subprocess is now suspended
proc_handle.resume()
# Subprocess is now running
问:如何在挂起状态下启动子进程?我知道创建子流程和暂停子流程之间的时间很少,但我对无缝解决方案感兴趣。另外,我知道我可以轻松地将子进程包装在父进程中,该父进程将在继续之前等待恢复信号,但如果存在的话,我想要一个不那么笨拙、更优雅的解决方案。此外,我知道我可以围绕子进程创建一个类包装器,直到我真正想要运行它才会创建它,但是我还没有为它分配 PID,我将无法检查统计信息,例如未启动进程的内存占用。
如果我能做到这一点,我会喜欢它:
cmd = ['binary', 'arg1', 'arg2']
proc = subprocess.pOpen(cmd, autostart=False) # autostart argument does not exist
# Subprocess was created, so it had a PID and has a memory footprint,
# but is suspended and no code had been run
当我使用 autostart=False 编写上述 pOpen 示例时,我意识到由于进程的运行方式,这可能是不可能的。如果我想在 main() 函数开始时中断,那么一些代码已经作为静态初始化的一部分执行了。理想情况下,子进程将在该步骤之前暂停,就在创建和初始化进程内存之后。
注意:我对在 linux 环境中解决此问题特别感兴趣,但如果存在独立于平台的解决方案,那就太好了。
在fork()
之后停止,在exec()
之前
这个很简单,虽然不是那么有用:
import subprocess, os, signal
proc = subprocess.Popen(
['binary', 'arg1', 'arg2'],
preexec_fn=lambda: os.kill(os.getpid(), signal.SIGSTOP),
)
为什么"没那么有用"?因为当preexec_fn
在新的 PID 中运行时,您的意图似乎涉及收集有关内存使用情况的统计信息(在某种程度上,可以在程序执行其malloc()
调用之前完成),并且在exec
发生之前,您将测量其内存的程序是 Python 解释器。
exec()
之后停止,在调用main()
之前
首先,为 Linux 加载程序编译一个审计模块 (ld.so
),类似于以下内容:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
unsigned int la_version(unsigned int version) {
return version;
}
/* To have stronger guarantees of immediacy, I might replace this with flock()ing a
* lockfile, and releasing that lock from the parent when ready to continue. YMMV,
* consider this a stub intended to be replaced.
*/
void la_preinit(uintptr_t *cookie) {
kill(getpid(), SIGSTOP);
unsetenv("LD_AUDIT"); /* avoid our children getting stopped the same way */
}
然后,在运行子进程时指定它:
newEnv = dict(os.environ)
newEnv['LD_AUDIT'] = '/path/to/above/library.so'
proc = subprocess.Popen(['binary', 'arg1', 'arg2'], env=newEnv)
加载程序在启动之前调用la_preinit
main()
。