【问题标题】:fork() in C programC程序中的fork()
【发布时间】:2012-02-15 19:10:28
【问题描述】:

这是最近的 GATE 入学考试中的一道题。
一个进程执行代码

fork();  
fork();  
fork();  

创建的进程总数为

(A) 3. (B) 4. (C) 7. (D) 8.

我的答案是(A) 3。

我的观点是每次fork()之后,都会创建1个子进程,并且父进程会正常继续执行。

教练机构给出的不可靠答案(没有任何解释)是(C) 7。

我认为他们认为每个分叉都会创建一个子进程和一个新的父进程。他们也在计算所有的父进程。 [我不允许发布图片,但我的朋友在图表中解释说,一棵树,每个左节点都分叉成两个节点。因此左侧有 4 个父节点,右侧有 3 个子节点。] 但问题清楚地只提到了子进程。而且我不认为父进程是在分叉中新创建的。

有人可以解释一些分叉的基本原理,以及上述问题的正确解决方案吗?

附:如果编程语言在分叉的概念上有任何不同,那么根据教学大纲,这应该是 C 或 C++ 程序。

【问题讨论】:

  • 由第一个进程创建的子进程自己继续到fork()。你也应该数一数。
  • 不,分叉是一个操作系统概念——编程语言无关紧要。
  • 这说明了为什么多项选择题对于展示理解是非常有害的。如果您必须写一个解释您如何得出答案的答案,即使您得出与“官方答案”不同的结论,您也可以获得理解这些概念的功劳。例如,是否要计算子进程的子进程?它改变了给出的答案。
  • 实际上,一个非常好的问题是:证明每个答案 (a) 3、(b) 4、(c) 7 和 (d) 8 的合理性。
  • @Rup 作为一个操作系统概念,在 windows 和 unix 上分叉会有所不同吗??

标签: c pthreads fork


【解决方案1】:

fork() 导致原始进程和一个子进程从代码中的该点开始。因此你有这张照片:

【讨论】:

  • @JonathanLeffler 呵呵,谢谢,你的回答做得很好,毕竟它更详细!
  • @eznme"-从代码中的那一点开始-"这是否意味着在第二次 fork 之后,孩子和父母都将继续从下一行(即第三个 fork() 语句)执行?
  • @AbhinavKulshreshtha 嗯,这样想:fork(); fork(); fork();开头有一个进程,有2个进程执行第一个分号,有4个进程执行第二个分号,有8个执行第三个分号的进程。 (然后减去 1,因为您只需要子进程)
【解决方案2】:

我认为总共有 8 个进程,或者原始的 7 个后代,或者原始的 3 个直接子代(其他是孙子和曾孙)。

  • 在第一个 fork() 之后,假设没有失败(整个),有两个进程。
  • 每个都再次执行fork() - 所以现在有四个进程。
  • 每个都再次执行fork() - 所以现在有八个进程。

【讨论】:

  • iit的官方答案前几天出来了。正确答案是 7。不幸的是,他们没有给出完整的解决方案,只是给出了答案。
【解决方案3】:

试试这个:

printf("initial pid: %d\n", (int)getpid());
fork();
fork();
fork();
printf("final pid: %d\n", (int)getpid());

【讨论】:

  • 我得到了 _getpid 和 _fork 的链接器错误。这是我使用的代码#include <stdio.h> #include <conio.h> void main() { printf("Initial pid: %d\n", (int)getpid()); fork(); fork(); fork(); getch(); }
  • 我在 windows 7 中的 dosbox 仿真下使用 turbo c++ 3.1
  • DOS 和 Windows 都没有fork()。您不能在那些操作系统中尝试该 sn-p。我不知道如何在 DOS 中做同样的事情;您可以在 Windows 中尝试CreateProcess()(与fork() 不完全相同)。
  • 不,DOS 一次只能运行一个进程,因此没有等效项。如果你想尝试这个,最好的办法可能是获取 VMware 播放器或类似设备并设置 Linux 虚拟机,或者在 Internet 上的某个地方找到一台可以获取 shell 帐户的 unix 机器。
  • 或者以 40 欧元购买一个 Raspberry Pi。它是具有 700MHz ARM SoC 的完整 Linux 机器。完全可以测试这种东西。
【解决方案4】:

每次调用 fork 后都会有两个进程,父进程和子进程。并且 两个 进程在分叉后立即继续执行。一些由此产生的过程(在所有分叉之后)既是父进程又是子进程。 only 子节点是进程树的 叶子only 是父级的那个(原始的)是树的 root。既是父母又是孩子的是分支

【讨论】:

  • 所以在上图中,children是底部的8片叶子,root node是parent。答案应该是 8。
  • @AbhinavKulshreshtha:在上图中,最左边的垂直线是原始进程,并且不是由示例中的任何fork() 创建的子进程。它某个其他进程的子进程,但我不会认为它是由fork(); fork(); fork() 创建的
  • 官方给出的答案是 7。他们没有提供完整的解决方案,但在此页面上,您的解释以及 @eznme 图是最简单的。谢谢
【解决方案5】:

第三次fork调用结束时,一共会有8个进程。在这 8 个进程中,将有 7 个子进程和 1 个父进程。

在解决这类问题时需要注意两点:

  1. fork() 调用返回两次,一次在父进程中,一次在子进程中。如果 fork 成功,则在子进程中返回 0 值,在父进程中返回非零值(子进程的 pid)。

  2. 子进程和父进程都在 fork 调用之后立即开始执行。

我已经借助图表和视频解释了上述问题。我希望你觉得它有用。

fork example

【讨论】:

    【解决方案6】:

    此类问题可以使用通用公式,

    进程总数为 2^n。

    获取创建的子进程总数的公式是 (2^n) - 1,其中 n 是调用 fork 函数的次数。

    这里 fork() 被调用了 3 次,所以子进程的数量将是 (2^3) - 1 = 7。 共有7个子进程和1个父进程。

    【讨论】:

      猜你喜欢
      • 2017-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 2021-12-11
      • 1970-01-01
      相关资源
      最近更新 更多