子进程似乎在创建之前运行代码。我该如何阻止它?

子进程似乎在创建之前运行代码。我该如何阻止它?

我正在尝试编写一个程序,该程序有一个父进程在 while 循环中创建多个子进程。为了进行测试,我开始尝试仅创建 4 个进程(1 个父进程及其 3 个子进程)。但看起来孩子们正在执行他们创建的行之上的代码,即使他们没有递归(据我所知)可以返回到该行。

这是我现在所拥有的:

int main() {

  time_t start;
  time_t end;
  int i = 0;
  pid_t pid;

  start = time(NULL);
  printf("Αρχική τιμή δευτερολέπτων %d\n", start);

  pid = fork();
  printf("%d ", pid);
  while (i < 2) {
    if (pid > 0) {
      fork();
      wait();
      i++;
    }
  }

  printf("check ");

  printf("%d", pid);

  if (pid > 0) {
    end = time(NULL);
    printf("%d\n", end - start);
  }

  return 0;
}

我的输出是:

Αρχική τιμή δευτερολέπτων 1547394155
29338 check 29338 0
29338 check 29338 0
29338 check 29338 0
29338 check 29338 0

所以看起来好像printf ("%d ", pid)运行了 4 次,尽管当时应该只运行 2 个进程。

答案1

这与“为什么使用 fork() 的程序有时会多次打印其输出?”。

当您执行此操作时,输出缓冲区不会立即刷新,printf("%d ", pid)因为字符串不是以换行符结尾,并且您没有调用fflush(stdout).这意味着未刷新的缓冲区由子进程继承,并且当缓冲区最终被最后一次printf()调用(输出换行符)或在程序执行结束时刷新时,您会多次输出原始父进程的 PID 。

fflush(stdout)在该调用之后直接插入printf()(以及包含适当的标头并wait()正确调用)将导致类似的结果

Αρχική τιμή δευτερολέπτων 1547400480
79301 0 check 793010
check 793010
check 793010
check 793010

另请注意,您将得到一个在循环中无限循环的进程while(第一个子进程,其pid值为零)。

答案2

首先,请注意,wait()不带参数的调用是不可接受的;它不等于wait(NULL);EFAULT当尝试存储状态时,它要么会失败,要么会浪费内存。

我将尝试解释您的代码中发生的情况,而不运行它(我也遇到过叉子炸弹,非常感谢)。

  pid = fork();
  printf("%d ", pid);
  while (i < 2) {
    if (pid > 0) {
      fork();
      wait();
      i++;
    }
  }

在第一个之后fork,您将有 2 个进程;在子进程中将pid等于0,因此子进程将继续无限循环运行,因为i++只有当 时才会执行pid > 0

从那时起,pid > 0在父级和由循环内部的第二个分支创建的所有子级中,该值都为 true,因为该pid变量永远不会在任何地方再次更新。

所以fork()从循环内部将创建(1)第一次在父母中奔跑的孩子,(2)父级中第二次运行的子级,并且(3)在循环的第一次运行中创建的子级中,第二次运行时还有另一个子级。

这使得 3 + 1 = 4 个进程,它们都将运行到函数的末尾main(),并且pid > 0所有进程都为 true,因此它们都会打印出整个内容(包括循环printf("%d ", ...之前添加的未刷新的数据) while)。


作为旁注,您应该dprintf(1 or 2, ...)在需要调试时随时使用printf();这将消除任何虚假的缓冲(以及对其发生的虚假恐惧);dprintf()现在也属于标准

相关内容