1

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

用户可以在提示符处输入作业,例如exe1 && exe2 &。与 BASH shell 类似,我只会exe2exe1成功退出时执行。此外,整个作业必须在后台执行(由尾随&操作员指定)。

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

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

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

任何反馈都会被应用。

4

2 回答 2

1

我看到两种方法:
1)用调用“sigwait”的循环替换你的sighandler(见man 3 sigwait)
然后在循环中

2)在开始创建管道之前,并在程序的主循环中使用管道句柄上的“选择”来等待事件。在信号处理程序写入管道和主循环处理情况。

于 2011-11-13T01:25:57.347 回答
0

嗯,这是一个很好的。

分叉两次,每个进程一次呢?第一个运行,第二个停止。在父 SIGCHLD 处理程序中,如果合适,将 SIGCONT 发送给第二个孩子,然后它会关闭并运行作业。自然地,如果第一个不应该运行,你会 SIGKILL 第二个,这应该是安全的,因为你不会真的设置任何东西。

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

于 2011-11-13T01:24:36.303 回答