5

wait()除了使用忙等待或忙睡眠循环之外,还有什么方法可以使用超时的系统调用?

我有一个fork自己的父进程和exec一个子可执行文件。然后它等待子进程完成,以任何适当的方式获取其输出,并执行进一步的处理。如果该进程在一定时间内没有完成,则假定其执行超时,并执行其他操作。不幸的是,鉴于问题的性质,这种超时检测是必要的。

4

3 回答 3

6

没有等待超时的呼叫。

您可以做的是安装一个为 SIGCHLD 设置标志的信号处理程序,并使用 select() 来实现超时。select() 将被信号中断。

static volatile int punt;
static void sig_handler(int sig)
{
    punt = 1;
}

...

struct timeval timeout = {10,0};
int rc;

signal(SIGCHLD, sig_handler);

fork/exec stuff
//select will get interrupted by a signal

rc = select(0, NULL,NULL,NULL, &timeout ); 
if (rc == 0) {
// timed out
} else if (punt) {
    //child terminated
}

如果您还需要处理其他信号,则需要更多逻辑

于 2013-08-27T22:11:04.610 回答
4

您可以waitpidWNOHANG选项和睡眠一起使用。

while(waitpid(pid, &status, WNOHANG) == 0) {
    sleep(1);
}

但这将是一个积极的睡眠。但是我看不到使用wait函数类型的其他方法。

于 2013-08-27T21:59:41.197 回答
3

在 linux 上,您也可以使用signalfd. signalfd本质上需要一组信号并创建一个您可以阅读的 fd;您读取的每个块都对应一个已触发的信号。(您应该使用 sigprocmask 阻止这些信号,以便它们不会实际发送。)

的优点signalfd是您可以将 fd 与selectpoll或一起使用epoll,所有这些都允许超时,并且所有这些都允许您等待其他事情。

注意:如果相同的信号在读取相应信号之前触发两次struct signalfd_siginfo,您只会收到一个指示。所以当你得到一个SIGCHLD指示时,你需要waitpid(-1, &status, &WNOHANG)重复直到它返回-1。

在 FreeBSD 上,您可以更直接地使用kqueue和 akevent类型来实现相同的效果EVFILT_PROC。(您也可以对 SIGCHLD 事件进行排队,但 EVFILT_PROC 允许您通过子 pid 指定事件,而不是全局为所有子进程指定事件。)这也应该适用于 Mac OS X,但我从未尝试过。

于 2013-08-27T23:40:49.637 回答