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
}

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

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

4

3 回答 3

2

如果您的意思是任何代码,那可能会很困难。您可以使用clonewithCLONE_STOPPED而不是fork将应用程序启动到停止状态(需要 SIGCONT 让它再次运行)。

但是,如果您只是指子代码中的特定代码并且您可以修改子代码,那么您可以作为 中的第一件事main,简单地为信号设置一个处理程序USR1(任何 IPC 都可能这样做,但信号似乎是最简单的特殊情况),然后等待它在继续之前触发。

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

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


但是,根据评论,由于您无权访问客户端代码,因此第一个选项可能是最好的,假设它SIGCONT实际上不会对孩子造成问题。这将需要测试。


当然,要记住的一件事是,既clone()不会也fork()不会实际将新程序加载到子进程中,这必须在拆分exec通过-type 调用来完成。这是 UNIX 拆分和功能的结果,详见此处forkexec

这意味着,虽然您不控制子程序但您确实控制了子进程,因此您的代码可以在加载新的子程序之前等待它想要的任何信号。因此,即使只是fork().

不幸的是,这也意味着在新程序加载后(至少不是确定性的)既clone不能也不能停止你的进程,所以,如果你想要做的是对新程序的摆弄(例如通过附加到它来操纵它的变量)记忆),你不能这样做。forkexec

您能做的最好的事情就是在新进程仍然有旧程序的副本(在exec.

于 2013-04-29T01:28:23.317 回答
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(); 看起来它应该让你在这里做你需要的。

于 2013-04-29T02:27:55.503 回答
0

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

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

在分叉之前,您设置一个变量要求孩子等待:-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
  }
}
于 2016-07-21T03:49:29.350 回答