使用 Boost 监控后代进程的创建
Posted
技术标签:
【中文标题】使用 Boost 监控后代进程的创建【英文标题】:Monitor descendant processes creation using Boost 【发布时间】:2015-01-20 14:06:32 【问题描述】:我正在我的程序中创建一个进程(比如说进程 X),它可能创建子进程,而且他们可能也这样做,而我正在无法确定进程树何时完成(=所有后代都已退出)。
我还没有找到任何直接的 Boost 方法来做到这一点。
我的(非防弹)解决方案是维护一个受监视进程的列表,从列表中的进程 X 开始,并定期监视系统中的进程,并在检测到进程它的父 ID 在列表中,将该进程 ID 也添加到列表中。一旦我进入一个监控周期,表明列表中的所有进程都已完成,那么进程树就完成了。
这种方法的两个主要问题是:
流程可能会“溜走” - 请考虑以下流程:
监控周期已结束,列表为 [X]。
进程 X 创建一个进程 Y,该进程创建 Z 并终止。
监控周期已开始 - 它不会检测到进程 Y,因为它 已经完成,它不会检测到进程 Z,因为进程 Y 是 未检测到。
这种类型的监控非常消耗资源 - 因为它需要非常频繁地运行才能最大限度地减少问题 1 中描述的这些“失误”。
我的程序中使用的一些代码sn-ps:
进程 X 创建:
m_process = ps::execute(
boost::process::initializers::set_cmd_line(...),
boost::process::initializers::bind_stdout(sink), // route stdout to a sink/pipe
boost::process::initializers::set_env(...),
boost::process::initializers::start_in_dir(...),
boost::process::initializers::throw_on_error());
Process X 监控(简单、不充分的情况):
boost::system::error_code ec;
int tmp = ps::wait_for_exit(m_process,timeout,ec);
重要提示:
-
我无法控制子进程(进程 X),我也不知道
它要做什么,或者它会产生什么进程。
我的解决方案应该同时适用于 windows 和 Linux(如果不是
可能,我将不得不求助于我的操作系统特定代码
程序,(到目前为止)与操作系统无关)。
【问题讨论】:
【参考方案1】:如果您可以更改子进程以使用某种 IPC 机制(标准输出、消息队列、共享内存、命名管道...)报告它们正在创建的 PID,那么您就可以开始了。
您可以将 Boost Asio 与获得的句柄一起使用 (object_handle
)。
否则,您可能会绑定到面向调试的接口(需要提升的权限),例如
Linux 上的 ptrace(参见例如 PTRACE_EVENT_VFORK
此处为 http://man7.org/linux/man-pages/man2/ptrace.2.html)
Windows:Waiting for grandchild processes in windows
我建议如果你控制子进程,你最好使用 IPC 来协调工作
【讨论】:
我无法控制子进程(进程 X),也不知道它要做什么,也不知道它会产生什么进程。我将在问题中添加这个重要说明。 @Ron.B.I 正如你所看到的,我已经找到了相关的答案。所以只有在 Linux 上,这可能会被证明是乏味的,除非其他人参与进来 关于答案:我们案例中的孙进程只是一个测试用例,我正在寻找一个通用的解决方案,我们正在谈论一个执行软件 - 能够执行由用户,在几种 Linux 风格和 Windows 上,用户可以运行一个脚本来启动一个安装,然后再运行另一个安装,诸如此类,我们这里唯一的知识是树的根,我的进程从它开始。关于 ptrace,我正在研究这个问题,但不幸的是,正如我所说,我正在尝试为 Windows 和 Linux 解决它。 @Ron.B.I 嗯。对于 windows 变体,它已经解决了!如果你真的想限制 Linux 上的资源使用,你可以使用chroot + ulimit
; ulimit 具有限制产生的子进程数量的功能,以及限制子 + 孙所消耗的总 CPU 时间(以及其他可创建的最大文件、打开文件的数量等)
我这样做的主要目的是防止下一个命令行被执行,直到第一个命令行完成它的树,给定获取有关正在生成的后代进程信息的逻辑(没有资源限制)我可以很容易监控并确定树已完成运行。以上是关于使用 Boost 监控后代进程的创建的主要内容,如果未能解决你的问题,请参考以下文章
boost::interprocess::message_queue 必须由写入它的进程创建?