2009-10-24 31 views
11

我已经在一个进程上完成了fork和exec(),但是我想在后台运行它。我怎样才能做到这一点? 我可以避免在它上面调用waitpid,但是这个过程永远坐在那里,等待将它的状态返回给父对象。有没有其他方法可以做到这一点?如何在C的后台执行()一个进程?

回答

5

捕获SIGCHLD并在处理程序中调用wait()。如果你忽略SIGCHLD,内核会自动清理僵尸进程(这是你在ps中看到的)。如果你忽略了SIGCHLD,内核会自动清理僵尸进程(这是你在PS中看到的)。这是一个很好的功能,但不便携。

+0

这是实施最干净的解决方案。谢谢! – 2009-10-24 19:38:33

+0

对于将来出现同样问题的程序员,下面是我在“UNIX环境下的高级编程”的第293页中找到的内容: SIGCHLD 只要进程终止或停止,就会将SIGCHLD信号发送给父进程。默认情况下,这个信号被忽略,所以如果父母想要在孩子的状态改变时得到通知,父母必须捕获这个信号。信号捕获函数中的正常操作是调用其中一个等待函数来获取子进程ID和终止状态。 在这种情况下,我只需要像liw.fi这样的一行提示: waitpid(-1,&status,WNOHANG | WUNTRACED); – 2009-10-24 19:47:00

-1

叉创建后台线程,然后执行。看到这个网站上的一个愚蠢的问题:Can we start a background process using exec() giving & as an argument?

+0

是的,我看到了这个问题,但它仍然没有回答我原来的问题。当然,我可以避免等待电话,但这个过程永远坐在那里。每次运行ps -al时我都可以看到它。 – 2009-10-24 19:00:36

+0

我不认为过去的问题的答案实际上回答了这个问题(因为aditya也抱怨); Avi给出了正确的答案。此外,我对过去的问题的答案实际上回答了这个过去的问题持怀疑态度(因为OP也想创建一个后台进程,没有人告诉他有关双叉的问题)。 – 2009-10-24 19:12:18

0

waitpid(-1, &status, WNOHANG)可能会做你所需要的:它应该立即返回,如果没有子进程退出。或者,您可以侦听SIGCHLD信号。

+0

这不是一个好策略 - 除非父进程准备好一遍又一遍地完成(否则你最终还是以僵尸结束)。 – 2009-10-24 19:13:29

+0

不幸的是,我得到了马丁预测的结果,但直到那时它肯定听起来很好。 – 2009-10-24 19:20:42

+0

这一切都取决于父进程的结构。有时偶尔进行轮询更容易,而不是抓住SIGCHLD。 – 2009-10-25 06:32:55

4

我认为你要做的是创建一个守护进程。阅读维基百科上的this链接以获得解释。

一个例子(从史蒂芬的UNIX环境高级编程)制作的过程的守护程序是:

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 

int daemon_int(void) 
{ 
    pid_t pid; 
    if ((pid = fork()) < 0) 
     return (-1) ; 
    else if (pid != 0) 
     exit(0) ; /* The parent process exits */ 
    setsid() ; /* become session leader */ 
    chdir("/") ; /* change the working dir */ 
    umask(0) ; /* clear out the file mode creation mask */ 
    return(0) ; 
} 

当然这并假设一个类似Unix的操作系统。

因此,您的程序包含上述功能,并在运行后立即调用它。然后从父进程中解除它,并将继续运行直到它终止或被杀死。

+0

嗯,仔细阅读这个问题让我觉得阿维可能会有答案。或者你可以让第一个孩子成为一个等待孙子终结的守护进程。所以哟打破父母和孩子之间的联系,所以父母可以终止而不导致孩子和孙子退出。 – Jackson 2009-10-24 19:19:57

+0

如果你想这样做,你也希望你的原始进程调用wait()来获得它的孩子。由于子进程会很快退出(在分支孙子之后),您的原始进程不会在wait()中长时间阻塞。 – 2009-10-24 19:20:46