Linux最佳实践:启动和监视另一个进程

4
在我的流程中,我需要启动/重新启动另一个进程。 目前我使用一个堆栈很小的线程和以下代码:
void startAndMonitorA()
{
  while(true)
  {
    system("myProcess");
    LOG("myProcess crashed");
    usleep(1000 * 1000);
  }
}

我觉得这不是最佳实践。我不清楚std::system()调用正在阻塞或浪费哪些资源。我使用的是嵌入式Linux,所以通常我会关心资源。

2个回答

3

其中一个有问题的部分是立即重启:如果子进程无法启动,这将导致100%的CPU使用率。这可能是子进程中的瞬态错误(例如无法连接到服务器)。在尝试重新启动之前添加至少一秒钟的暂停可能是一个好主意。


Linux上的system调用的作用是:

  1. 设置信号SIGINTSIGQUIT被忽略。
  2. 阻止信号SIGCHLD
  3. fork()
  4. 子进程调用exec() shell,将命令行传递给shell。
  5. 父进程调用waitpid(),阻塞线程直到子进程终止。
  6. 父进程恢复其信号状态。

如果您要重新实现system的功能,则可能会省略步骤5(以及步骤1、2和6),以避免阻塞线程并依靠SIGCHLD在子进程终止时收到通知并需要重新启动。

换句话说,最少的要求是为SIGCHLD设置信号处理程序,并调用forkexec


我在中间添加了sleep,实际代码中已经像这样了,我只是试图让示例尽可能简单。我想暂时使用std::system()调用。 - florgeng

-1

所示的代码对大多数情况都足够了。如果您真的关心资源使用情况,那么您应该知道,对于您正在监视的每个进程,您都要启动(并保留)一个线程。如果您的程序已经有事件循环,那么可以通过付出一些额外的努力(并增加复杂性)来避免这种情况。

实现此操作需要执行以下操作:

  • 不要调用system(),而是使用fork()exec()启动外部程序。将其PID存储在全局表中。
  • 设置SIGCHLD处理程序,通知事件循环子进程的退出,例如通过向事件循环监视的管道写入一个字节。
  • 当子进程退出时,在循环中使用带有WNOHANG标志的waitpid运行,只要还有要回收的子进程就一直运行。 waitpid()将返回退出的子进程的PID,因此您知道要从表中删除其PID,并安排重新启动它的超时。

以某种方式启动外部程序,并通过捕获它们的SIGCHLD并重新启动它们来监视所有已启动的程序的单个线程。这将节省多个线程和多个打开的sh解释器的资源 - 据我所知! - florgeng
@florgeng 是的;如果最小化资源是您的目标,那么为每个启动的进程生成一个线程有些浪费。即使仍然使用 system(),也可以避免多个打开的 sh 解释器,只需在命令前面加上 exec。例如,system("sleep 10") 将等待 sh 完成(这将反过来等待 sleep 完成),而 system("exec sleep 10") 将启动 sh,它将立即被 sleep 替换,因此您正在等待的唯一进程是 sleep - user4815162342

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接