【问题标题】:Understanding how fork() and wait() work together了解 fork() 和 wait() 如何协同工作
【发布时间】:2014-09-10 13:16:07
【问题描述】:

这不在代码审查中,因为我不了解代码的完整概念。如果仍然需要移动,请告诉我。

我有一些代码,我想解释一下我对它的想法,我希望有人能告诉我哪里出了问题或感到困惑,因为我仍然不完全确定发生了什么。

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main()
   {
   pid_t pid, pid1;
   pid = fork();

   if (pid < 0) {
      fprintf (stderr, “fork() failed\n”);
      return(1);
   }
   else if (pid == 0) {
      pid1 = getpid();
      printf (“pid = %d\n”, pid); // A
      printf (“pid1 = %d\n”, pid1); // B
   }
   else {
      pid1 = getpid();
      printf (“pid = %d\n”, pid); // C
      printf (“pid1 = %d\n”, pid1); // D
      wait (NULL);
   }
   return 0;
}

据我了解,我们有两个进程 ID,父 (pid) 和子 (pid1)。 一旦我调用pid = fork(),我相信孩子被启动并被赋予0的id,而父母得到孩子的ID,比如说1337。所以pid = 1337和pid1 = 0。

所以我们跳过第一个if,因为没有发生错误(pid if,因为pid不等于0,然后我们输入最终的if,其中C将打印 1337 和 D 将输出 0。

我认为这会等到孩子完成。

之后,我假设复制的进程 (fork()) 将运行 else if (pid == 0),但我不知道为什么,因为 pid 仍然是 1337..

TLDR:如果应该先执行第三个if,那么我如何到达第二个if,但如果这个逻辑完全错误,请纠正我。

【问题讨论】:

  • 请缩进你的代码。总是。
  • @MichaelWalz 刚刚做了,我的错
  • 阅读维基页面fork、手册页fork(2)Advanced Linux Programming;这些困难的事情解释了无数次!
  • @BasileStarynkevitch 我知道并且我理解,但仍然没有点击,因此我在这里问我通常会在哪里获得几个视图和/或解释。

标签: c linux fork wait


【解决方案1】:

fork 创建一个(近乎完美的)正在运行的进程的副本。正如您所推测的,其中一个区别是fork() 本身的返回值。因此,假设 fork 工作,您有两个进程执行相同的代码。一是孩子采用if (pid == 0) ... 路径,而父母采用else... 路径。您没有关于这两个进程工作的顺序的信息。也许孩子先走,也许父母先走,也许一半他们轮流走,也许你有两个处理器,它们一起运行......

想象一下,您将这个程序写在一张纸上,并用手指跟随,沿着页面向下滑动。当你到达叉子时,把纸拿到复印机,复印,把两张纸放在桌子上,把每只手的食指放在其中一张上,移动你的两根手指,每个手指向下滑动自己的一张纸。

【讨论】:

  • 好吧,这也是有道理的,你介意看看我对 ralph 帖子的评论并告诉我我做错了什么吗?
  • 我相信他对您的评论的回答是正确的。在 fork 之后,每个进程都有自己的所有变量的副本。子进程中变量的值一开始就是它们在父进程中的任何值,但它们是完全独立的,父进程中的更改对子副本没有影响,反之亦然。
  • 好的,我快到了,但我仍然对 pid 感到困惑。当子副本启动时,您说它从 pid == 0 开始。但是如果我们在该点进行复制,那么 pid = child_ID 和 pid1 = 0 吗?或者子进程是否转移到它自己版本的 pid 以提供 pid = 0?这有意义吗?
  • 我不确定我是否完全遵循您的问题,但是一旦fork() 通过复制父进程来构造子进程,在那之后它们就完全分开了。这种分离包括fork()返回到每个副本的值(父副本获取子副本的pid,子副本获取0)。在fork() 之后有两个完全独立的变量,名为pid,每个进程中都有一个。
  • ooooh,所以它们在 fork 本身之后没有相同的变量分配。所以在父进程中pid = child_id,在子进程中pid = 0。那么pid1是什么?也许我对 pid1.. 的目的/目标感到困惑?
【解决方案2】:

你说的都不对

在执行fork() 调用后,子进程和父进程并行运行,都执行fork() 之后的程序代码。唯一的区别是pid。子进程将使用 pid = 0 运行相同的程序,而父进程将使用 pid = (子进程的 pid) 运行相同的程序。它们分开,都拥有程序所有变量的副本,但 pid 变量的副本不同。

【讨论】:

  • 好吧,这是有道理的。所以我们有两个程序,每个版本都有一个父子程序。所以两个问题。 1. 如果我们运行这个程序,那么 A,B,C,D 的输出真的来自两个不同的程序吗?如果是(或不是),是否会有值:A = 0,B = child_ID,C = child_ID,我对 D 感到困惑。
  • 是的,输出来自 2 个不同的进程。 A 和 B 来自子进程。 C 和 D 来自父进程。 D是父进程的pid。 B 和 C 相等,并且是您创建的子进程的 pid。但是,您不知道打印 A、B、C 或 D 的顺序。您应该在输出前加上一些东西来识别它。
  • @nos 好吧,如果我最初被告知父 ID 是 123,子 ID 是 456。那么 A = 0,B = 456,C = 456, D = 123?
  • 好吧,在我看来这是有道理的,但是当我逐行浏览代码时,我仍然对 fork() 发生后的变量值有些困惑。在我看来,我们启动程序,pid = 123,pid1 = 456。我们点击 fork(),然后制作了两个副本,我认为发生的是两个副本的值 pid = 456 和 pid1 = 0。这一定是错误的,因为子副本不会运行 pid == 0,并且在父进程中打印出 C 和 D 会给出不正确的值。在 fork 的变量分配过程中我遗漏了什么?
【解决方案3】:

pid在child中为0,在parent中为child的进程ID。

pid1 设置为 当前 进程的进程 ID。 pid1 的子副本中的值与pid 的父副本中的值相同。

【讨论】:

    猜你喜欢
    • 2012-01-03
    • 1970-01-01
    • 2019-01-16
    • 1970-01-01
    • 1970-01-01
    • 2011-02-26
    • 2013-12-09
    • 2014-04-21
    • 2015-12-17
    相关资源
    最近更新 更多