wait()
除了使用忙等待或忙睡眠循环之外,还有什么方法可以使用超时的系统调用?
我有一个fork
自己的父进程和exec
一个子可执行文件。然后它等待子进程完成,以任何适当的方式获取其输出,并执行进一步的处理。如果该进程在一定时间内没有完成,则假定其执行超时,并执行其他操作。不幸的是,鉴于问题的性质,这种超时检测是必要的。
wait()
除了使用忙等待或忙睡眠循环之外,还有什么方法可以使用超时的系统调用?
我有一个fork
自己的父进程和exec
一个子可执行文件。然后它等待子进程完成,以任何适当的方式获取其输出,并执行进一步的处理。如果该进程在一定时间内没有完成,则假定其执行超时,并执行其他操作。不幸的是,鉴于问题的性质,这种超时检测是必要的。
没有等待超时的呼叫。
您可以做的是安装一个为 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
}
如果您还需要处理其他信号,则需要更多逻辑
您可以waitpid
与WNOHANG
选项和睡眠一起使用。
while(waitpid(pid, &status, WNOHANG) == 0) {
sleep(1);
}
但这将是一个积极的睡眠。但是我看不到使用wait
函数类型的其他方法。
在 linux 上,您也可以使用signalfd
. signalfd
本质上需要一组信号并创建一个您可以阅读的 fd;您读取的每个块都对应一个已触发的信号。(您应该使用 sigprocmask 阻止这些信号,以便它们不会实际发送。)
的优点signalfd
是您可以将 fd 与select
、poll
或一起使用epoll
,所有这些都允许超时,并且所有这些都允许您等待其他事情。
注意:如果相同的信号在读取相应信号之前触发两次struct signalfd_siginfo
,您只会收到一个指示。所以当你得到一个SIGCHLD
指示时,你需要waitpid(-1, &status, &WNOHANG)
重复直到它返回-1。
在 FreeBSD 上,您可以更直接地使用kqueue
和 akevent
类型来实现相同的效果EVFILT_PROC
。(您也可以对 SIGCHLD 事件进行排队,但 EVFILT_PROC 允许您通过子 pid 指定事件,而不是全局为所有子进程指定事件。)这也应该适用于 Mac OS X,但我从未尝试过。