2011-11-13 27 views
1

我目前正在C++中构建一个小外壳的过程。根据以前任务的sigchld()执行新任务

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

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

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

以上所有需要能够在后台进行,我想避免让jobManager坐在等待exe1的繁忙等待中返回。我还希望没有一个单独的线程,只是等待开始执行另一个进程。但是,指示我的jobManagerSIGCHLD处理程序开始执行下一个进程看起来很糟糕的代码。

任何反馈appriciated。

回答

1

我看到有两种方式:
1)更换您与循环调用 “调用sigwait” sighandler(见男子3调用sigwait)
然后在循环

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

+0

啊 - 你的select()方法对我来说很有意思。我在套接字编程中使用了select()/ poll(),并且希望在这里做类似的事情以避免忙碌的等待。但是,我猜管道需要'全局',因为我无法在运行时向信号处理程序提供任何信息。 – BSchlinker

+0

sigwait循环很丑,在这里做得不好,因为它们需要做后台工作。 – Robert

+1

你可以处理这个没有全局变量,但在linux特定的方式:signalfd为你创建描述符来获取有关信号的信息。 – fghj

0

嗯,这是一个很好的。

怎么样分两次,每个过程一次?第一个运行,第二个停止。在父项SIGCHLD处理程序中,发送一个SIGCONT给第二个孩子(如果适用的话),然后关闭并运行作业。自然地,如果第一个不应该运行,那么SIGKILL第二个应该是安全的,因为你不会设置任何东西。

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

+0

我想避免这种解决方案的唯一原因是因为从我的角度来看,它似乎是一种不幸的资源浪费。还有一些我想要处理的高级情况,例如作业中的()循环。 – BSchlinker

+0

@BSchlinker这不是真的浪费资源,除非你的子进程做了很多。fork()是写时复制,所以等待过程中可能使用了一个KB左右的文件,并且没有CPU时间,因为它会被阻塞。 – Robert