我目前正在使用C ++构建一个小shell。
用户可以在exe1 && exe2 &
等提示下输入作业。与BASH shell类似,如果exe2
成功退出,我将只执行exe1
。此外,整个作业必须在后台执行(由尾随&
运算符指定)。
现在,我有一个处理作业执行的jobManager
和一个job
结构,其中包含作业的可执行文件及其各自的参数/条件。通过调用fork()
然后使用正确的参数调用execvp()
来启动作业。当作业结束时,我有SIGCHLD
的信号处理程序,我在其中执行wait()
以确定哪个进程刚刚结束。当exe1
结束时,我会观察其退出代码,并确定是否应继续启动exe2
。
我关心的是如何启动exe2
。我担心如果我从我的SIGCHLD
处理程序的上下文中使用我的jobManager启动函数,我可能最终会在堆栈上挂出太多SIGCHLD
处理程序函数(如果有10个条件执行,例如)。另外,从信号处理程序开始下一次执行似乎不是一个好主意,即使它是间接发生的。 (我在1.5年前尝试做类似的事情,当时我正在学习信号处理 - 我似乎记得它在我身上失败了。)
以上所有需要能够在后台进行,我希望避免让jobManager
坐在忙碌的等待中exe1
等待返回。我还希望没有一个单独的线程,只是等待开始执行另一个进程。但是,指示我的jobManager
从SIGCHLD
处理程序开始执行下一个进程似乎是糟糕的代码。
任何反馈都是适当的。
答案 0 :(得分:1)
我看到两种方式:
1)用称为“sigwait”的循环替换你的sighandler(见man 3 sigwait)
然后在循环中
2)在开始创建管道之前,在你的程序的主循环中使用管道句柄上的“select”来等待 事件。在信号处理程序中写入管道,并在mainloop处理情况。
答案 1 :(得分:0)
嗯,这是一个很好的。
两次分叉,每个过程一次?第一个运行,第二个停止。在父SIGCHLD处理程序中,如果适用,将SIGCONT发送给第二个子节点,然后该节点将关闭并运行该作业。当然,如果第一个不应该运行,你可以SIGKILL第二个,这应该是安全的,因为你不会真正设置任何东西。
听起来怎么样?你将有一个无所事事的过程,但它不应该持续很长时间。