4

子进程和父进程执行是并行的,首先启动取决于操作系统调度。但是可以做些什么来让孩子总是在父母之前开始呢?

这是我的问题的伪代码,

int start_test()
{
   pid_t pid;
   pid = fork();
   if(pid == 0) {
      execv("XXX", XXX);
   } else if(pid > 0) {
     pid = fork();
    if(pid == 0) {
       execv("XXX", XXX);
    } else {
       // Do something
    }
   }
  return 0;
}
int main()
{
   start_test();
   return 0;
}

我想让第一个 execv 先执行,然后父级再次创建新进程。每个 execv 都应该按顺序排列。

4

6 回答 6

7

我真的不知道为什么人们一直告诉不要依赖这种行为,它实际上在跟踪程序(strace,ldtrace,...)中使用了很多。

首先,fork 进程并获取子 pid,停止子进程,然后在父进程中恢复它:

pid_t pid = fork();
if (pid == -1)
    abort();
else if (pid == 0) {
    raise(SIGSTOP); // stop the child
} else {
    waitpid(pid, NULL, WUNTRACED); // wait until the child is stopped
    kill(pid, SIGCONT); // resume the child
}
于 2015-05-16T14:22:30.630 回答
1

您可以在(POSIX 线程)的情况下实现这一点pthread,但在进程的情况下则不行。看,进程调度始终掌握在内核手中,您无法显式操作。在并行处理系统中,所有进程(无论是子进程、父进程还是其他僵尸进程)都是并行执行的,您无法更改。该sleep()方法可以工作,但这是非常糟糕的方法。

1. 利用信号处理。

当你fork()有一个新的子进程时,你sleep()还是pause()父进程。子进程将在父进程处于等待位置的地方执行。然后子进程发送自定义信号,该信号将由父进程处理以继续执行。(这也很忙,因为您需要在程序中处理信号)。

2. 通过使用系统调用。

通过使用系统调用,您可以处理进程状态(就绪、暂停、终止等)。某些 shell 命令隐式使用系统信号处理来更改进程状态/优先级。如果您知道 processID (pid),那么您可以执行以下操作:

kill -SIGSTOP [pid]
kill -SIGCONT [pid]

在 c 编程的情况下,您可以执行以下操作:

system("kill -SIGSTOP [pid]"); //pause

system("kill -SIGCONT [pid]"); //resume

如需更多参考,您可以打开此页面。

此外,如果你能指定你要在哪里实现这个东西的实际问题,我可以适当地建议你。

于 2015-05-16T13:58:55.743 回答
0

不能保证一个进程被安排在另一个进程之前。即使您将父sleep()进程设置为 ,如果其他进程在分叉之后立即抢占了父进程,也很可能发生子进程首先执行的情况。孩子和父母可以很好地在两个 CPU 上真正并行运行。

实际上,这样做没有任何价值。如果两个进程之间需要某种同步,请使用管道/信号等显式机制。

简而言之:不要编写代码来依赖无法保证的行为。

线程提供了更多机制来同步并行代码执行。你可以看看 pthread。请注意,线程 - 与进程不同 - 共享内存等资源,这可能会带来其他问题。

于 2015-05-16T14:09:57.183 回答
0

使用初始值为 0 的二进制信号量。分叉后,父级应等待信号量。child 启动后,它可以发出信号量(即设为 1)。然后,父母的等待将结束,它将继续进行。

于 2015-05-16T17:10:10.320 回答
0

在linux中如果想让子进程先运行,需要使用kernel.sched_child_runs_firstsysctl参数

于 2015-05-16T17:17:31.660 回答
0

只需等待(0);在父级内部。所以父母会等到孩子完成。

if(child){
 //do whatever
}
if(parent{
wait(0);
// so whatever
}
于 2016-09-26T03:56:47.523 回答