2014-03-31 37 views
0

我想fork()一个子进程,然后调用execl()用一个新的进程替换子进程映像,这个进程可能不会停止(将会停留在while循环中或者期望输入,例如它不应该)。
我想等待它不超过X秒。
它应该是这个样子的是:等待一个不超过X秒的子进程

int main() { 

    pid_t pid=fork(); 
    if (pid==-1) { 
     perror("fork() error"); 
    } 
    else if (pid==0) { 
     //call execlp("exe.out","exe.out",arg1, ... ,NULL) 
     //where exe.out might not stop at all 
    } 
    else { 
     //wait for X seconods, and if child process didn't terminate 
     //after X seconds have passed, terminate it 
    } 
} 

wait()和waitpid函数()不提供此功能。
怎么办?

谢谢!

+0

'waitpid()'有一个'WNOHANG'标志,它允许你测试孩子是否已经退出而没有阻塞。 –

+0

似乎应该有一个更简单的方法来做到这一点,但可以安装一个'SIGCHLD'信号处理程序,它会在孩子退出时通知您,因此您可以安装一个信号处理程序,它将通过您的主线程执行一个管道,然后你的主代码路径将等待一个超时的管道接收端的'select'。 – mkimball

+0

嗨@PP。,感谢您的评论。 Linux手册页说,如果我设置了WNOHANG,它将“如果没有孩子退出就立即返回”。我可以在哪里指定X秒? –

回答

3

您可以设置一个信号处理器警报,在X秒后熄灭,然后等待(2)。如果等待返回,则子状态在X秒之前改变。如果信号处理程序返回,则不会更改子状态。

如果wait(2)返回,请不要忘记重置警报。

+0

嗨@ mpez0,感谢您的帮助。说实话,我不知道信号处理器的警报是什么(可能是我们在课程中没有学到的东西),但是我发现有sleep()系统调用。它能以某种方式工作吗? –

+1

睡眠(第3章)作为库函数通常使用警报(第2章)系统调用来实现。您需要比单独提供的睡眠(3)更多的功能,并且您可以使用警报(2)或信号(2)来执行此操作。你可以通过使用sleep(3)等待X秒,然后用NOHANG执行waitpid(2)来简化事务,但是你总是会让X暂停。如果这对你来说是一个很好的权衡,那么做吧。 – mpez0

0

您可以创建多生一个孩子杀死pid过程中,如果它不从父接收信号pid过程超时前结束(伪):

in_, out = pipe() 
pid2 = fork() 
if pid2 != 0: # parent 
    close(in_) 
    waitpid(pid, 0) # wait for child to complete 
    write(out, b'1') # signal to pid2 child to abort the killing 
    waitpid(pid2, 0) 
else: # child 
    close(out) 
    ready, _, _ = select([in_], [], [], timeout) # wait `timeout` seconds 
    if not ready: # timeout 
     kill(pid, SIGTERM) 
     write(2, b"kill child") 
    else: 
     write(2, b"child ended before timeout") 
    _exit(0) 

这里的complete code example

在Linux上,它被实现为eventfd(2)