基于前一个任务的sigchld()执行新任务

Executing new task based on sigchld() from previous task

本文关键字:执行 新任务 sigchld 于前一 任务      更新时间:2023-10-16

我目前正在用c++构建一个小shell。

用户可以在提示符下输入作业,例如exe1 && exe2 &。与BASH shell类似,如果exe1成功退出,我将只执行exe2。此外,整个作业必须在后台执行(由后面的&操作符指定)。

现在,我有一个jobManager处理作业的执行,job结构包含作业的可执行文件和它们各自的参数/条件。作业通过调用fork(),然后使用适当的参数调用execvp()来启动。当一个作业结束时,我有一个SIGCHLD的信号处理程序,我在其中执行wait()来确定哪个进程刚刚结束。当exe1结束时,我观察它的退出代码,并决定是否应该继续启动exe2

我关心的是如何启动exe2。我担心,如果我从SIGCHLD处理程序的上下文中使用jobManager start函数,我最终可能会在堆栈上挂起太多的SIGCHLD处理程序函数(例如,如果有10个条件执行)。此外,从信号处理程序开始下一个执行似乎不是一个好主意,即使它是间接发生的。(我在1.5年前尝试过类似的事情,当时我刚刚学习信号处理——我似乎记得它在我身上失败了)。

以上所有需要能够在后台发生,我想避免让jobManager坐在繁忙的等待中,只是等待exe1返回。我也不希望有一个单独的线程等待另一个进程的开始执行。然而,指示我的jobManagerSIGCHLD处理程序开始执行下一个进程似乎是糟糕的代码。

我认为有两种方法:
1)用调用"sigwait"的循环替换你的sighandler(参见man 3 sigwait)
然后in loop

2)在开始创建管道之前,在程序的主循环中使用"select"在管道句柄上等待事件。

嗯,这个不错。

如果每个进程分叉两次呢?第一个跑了,第二个停了。在父SIGCHLD处理程序中,如果合适的话,将SIGCONT发送给第二个子处理程序,然后该子处理程序启动并运行作业。自然地,如果第一个不应该运行,您可以SIGKILL第二个,这应该是安全的,因为您实际上没有设置任何内容。

听起来怎么样?您将有一个进程无所事事,但它不应该持续很长时间。