让subprocess等待父进程

我必须在C中编写一个程序,它将fork一个新的进程,然后使用该进程的pid来执行另一个函数。 不过,我需要在subprocess运行之前调用这个函数,我不知道该怎么做。

这是我正在尝试做的一些伪代码。

 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 } 

如果你需要任何额外的信息,请询问。 谢谢。

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

如果你的意思是任何代码,这可能是困难的。 您可以使用clone CLONE_STOPPED而不是fork来启动应用程序进入停止状态(需要使用SIGCONT来重新启动它)。

但是,如果您只是指子代码中的特定代码,并且您可以修改子代码,那么可以首先设置USR1信号的处理程序(任何IPC可能都会执行,但信号似乎是最简单的在这个特定的情况下),然后等待它开火,然后再继续。

这样,这个过程本身就会运行,但是还没有做任何事情。

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


但是由于根据评论,您无法访问客户端代码,因此假设SIGCONT实际上不会导致儿童出现问题,那么第一种选择可能是最好的。 这将需要测试。


当然,要记住的一件事情是clone()fork()都不会真的把你的新程序加载到子进程中,这必须在拆分之后用一个exec -type调用来完成。 这是forkexec功能之间的UNIX拆分的结果,在这里详述。

这意味着,虽然你不控制子程序,但是你控制子程序,所以你的代码可以在加载新的子程序之前等待它想要的任何信号。 因此即使使用fork()也是可行的。

不幸的是,这也意味着clonefork都不能阻止你的进程,因为新程序已经被exec加载(至少不是确定性的),所以如果你想要做的是对新程序的调整(比如通过操作变量附加到它的记忆),你不能这样做。

你可以做的最好的事情是在旧的程序拷贝(在exec之前)的时候,完成新的程序。

有一个更简单的方法,假设你的操作系统将让你分享地址空间之前的孩子高管。 伪码如下。

 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() ; 它看起来应该让你做你需要在这里。

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

它的工作方式(大致): –

分叉之前,你设置一个变量,要求孩子等待: – child_continue = false

1.)CHILD过程开始执行(或父母,无所谓)

  • 如果变量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 } }