2013-04-29 215 views
3

我必须在C编写一个程序,将fork一个新进程,然后使用该进程pid作为另一个函数。不过,我需要在子进程运行之前调用这个函数,我不知道该怎么做。让子进程等待父进程

下面是我试图做的一些伪代码。

pid_t pid = fork(); 
if(in_child){ //In the child process 
    //launch child application 
    //somehow stop the child application before it actually executes any code 
} 
else{ 
    //call my function with the child's pid 
    //resume the child process 
    //do other stuff 
} 

如果您需要任何其他信息,请询问。谢谢。

编辑:我没有访问孩子的代码。我只是想运行一个可执行文件。

+0

如何使用管道并让子进程等待管道中出现的东西? – 2013-04-29 01:26:40

+2

使用信号量。 – Duck 2013-04-29 01:26:51

+0

你打算如何处理父母的孩子的PID?您可以在执行子应用程序之前简单地让分叉的孩子等待父母准备好吗?为什么不? – 2013-04-29 04:28:03

回答

2

如果你的意思是任何代码,那可能很困难。您可以使用cloneCLONE_STOPPED而不是fork来启动应用程序进入停止状态(需要SIGCONT才能使其重新开始)。然而,如果你只是指子代码中的特定代码,并且你可以修改子代码,那么你可以像main中的第一件事情那样简单地设置一个USR1信号的处理程序(任何IPC可能只会做一个信号在这种情况下似乎是最简单的),然后在继续之前等待它发射。

这样,过程本身将运行,但不会做任何事情。

然后,您可以让父母编织它需要做的任何魔法,然后发送一个SIGUSR1给孩子。


但因为根据注释,你不访问客户端代码,第一个选项可能是最好的,假设SIGCONT实际上不会引起孩子的问题。这将需要测试。


当然,有一点要记住的是,无论是clone()也不fork()实际上将载入的新程序进入孩子的过程中,必须要后与exec型呼叫完成分裂。这是forkexec功能之间的UNIX拆分的结果,详细的here

这意味着,当你不控制孩子程序,控件的子过程,因此您的代码可以等待加载了新的子程序之前,它希望任何信号。因此,即使只有fork()也是可行的。

不幸的是,这也意味着新的程序已经加载后exec(至少不确定性)既不clone也不fork可以停止你的过程是这样,如果摆弄你想要做的就是将新的程序(如通过附加内存来操纵变量),你不能这样做。

您可以做的最好的做法是在新程序仍在运行时(在exec之前)拷贝旧程序。

+0

不幸的是,这不会工作,因为我没有访问孩子的代码,所以我不能把任何东西放在它的主要方法。 – 2013-04-29 01:34:18

+1

@Zac,那么你应该尝试'clone'选项。它仍然使用信号,但希望不需要访问源代码。通过在前台运行孩子轻松进行测试,使用CTRL-Z将其停止,然后使用“fg”重新启动它。如果它在没有投诉的情况下生存下来,它应该使用'clone/CLONE_STOPPED/SIGCONT'。 – paxdiablo 2013-04-29 01:36:53

1

有一种更简单的方法,假设您的操作系统将允许您在儿童执行官之前共享地址空间。伪代码如下。

volatile int barrier; 

int safe_fork(routine_to_call) 
{ 
    pid_t pid; 

    barrier = 0; 
    pid = fork(); 
    if (pid == 0) { 
     /* parent */ 
     routine_to_call() 
     barrier = 1; 
    } else if (pid > 0) { 
     while (barrier = 0) 
      ; /* or sleep if it's a slow routine */ 
     exec() 
     //if we get here, exec failed; exit with failure code 
    } else { 
     /* return failure */ 
    } 
    /* must be parent; return success */ 
} 

您可能需要做一些特殊的事情来获取共享行为,而不是让它们都以独立副本开始。我知道它在FreeBSD上可行。在linux中,查看CLONE_VM标志为clone();它看起来应该让你在这里做你所需要的。

0

你在找什么是进程间条件变量。 https://en.wikipedia.org/wiki/Monitor_(synchronization)

它会工作(大约)方式: -

分叉你之前设置一个变量,询问孩子等着: - child_continue = false

1)子进程开始执行(或父,没有按“T物质)

  • 如果变量child_continue == false
  • 休眠条件变量和等待信号从父

2.)父进程等待其运行的机会(注意运行顺序无关紧要)。当父进程准备好运行时,它可以通过子PID(或其他)执行任何想要的操作,并指示子进程继续。

为了做到这一点,你需要进程间互斥和进程间条件变量。

//#include "pthread.h" in main file 

//create IPC MUTEX which can be shared by both child and parent. 

pthread_mutexattr_t mutex_attr; 
pthread_condattr_t cond_attr; 
pthread_mutex_t mtx; 
pthread_cond_t cond; 
if (0!= pthread_mutexattr_init(&mutex_attr)) 
{ 
//errror handling 
} 
if (0!= pthread_condattr_init(&cond_attr)) 
{ 
//errror handling 
} 

if (0 != pthread_condattr_setpshared(&cond_attr,PTHREAD_PROCESS_SHARED) 
{ 
//error handling 
} 
if (0 != pthread_mutexattr_setpshared(&mutex_attr,PTHREAD_PROCESS_SHARED) 
{ 
//error handling 
} 

if (0 !=pthread_mutex_init(&mtx,&mtx_attr)) 
{ 
//error handling 
} 

if (0 !=pthread_cond_init(&cond,&cond_attr)) 
{ 
//error handling 
} 
boolean child_continue = false; 
//now fork !! 

pid_t pi = fork(); 
if (pi ==0) //child 
{ 
    if (0 !=pthread_mutex_lock(&mtx)) 
    { 
    //error handling 
    } 
    while (!child_continue) //wait until we receive signal from parent. 
    { 
    if (0 !=pthread_cond_wait(&cond,&mtx)) 
    { 
    //error handling 
    } 
    } 
    if (0 !=pthread_mutex_unlock(&mtx)) 
    { 
    //error handling 
    } 
    //Parent is done!! either we woke up by condition variable or, parent was done before hand 
    //in which case, child_continue was true already. 
} 
else 
{ 
    //in parent process do whatever you want with child pid (pi variable) 

    //once you are done, set child_continue to true and wake up child. 
    if (0 !=pthread_mutex_lock(&mtx)) 
    { 
    //error handling 
    } 
    child_continue = true; 
    if (0 !=pthread_cond_signal(&cond)) 
    { 
    //error handling 
    } 
    if (0 !=pthread_mutex_unlock(&mtx)) 
    { 
    //error handling 
    } 
}