【问题标题】:What does this C code do?这段 C 代码有什么作用?
【发布时间】:2011-04-13 10:13:16
【问题描述】:

我对 C 编程真的很陌生,虽然我做过很多其他类型的编程。

我想知道是否有人可以向我解释为什么这个程序输出 10。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

int value = 10;

int main()
{
    pid_t pid;

    pid = fork();
    if(pid == 0){
    value += 10;
    }
    else if(pid > 0){
        wait(NULL);
        printf("parent: value = %d\n", value); //Line A
        exit(0);
    }
}

我知道输出是“父级:值 = 10”。有人知道为什么吗?

谢谢!

【问题讨论】:

  • 谢谢大家!完全明白现在发生了什么!
  • 这是一些编程课程中常见的作业问题,它的作业不是吗?
  • 如果您对答案感到满意,那么标记最佳答案是一个好习惯。这将奖励发布者并让其他人知道问题已经解决。

标签: c++ c fork


【解决方案1】:

关于 fork() :

  • 如果 fork() 返回负值, 子进程的创建是 失败。
  • 如果 fork() 返回一个零到新的 创建子进程。
  • 如果 fork() 返回正值,则 子进程的进程ID,到 父母。

所以在你的情况下,它一定会返回一个大于 0 的数字,因此该值将保持 10 并且将被打印出来。

【讨论】:

  • 很棒的答案。我正试图解决这个问题。所以父进程得到一个大于 0 的数字,因此进入 else 部分并打印。子进程得到一个 0。这个子进程做什么?它是否会创建一个从当前行执行的新进程?还是从代码的开头?
  • @kralco626 它是父进程的副本,从同一点/状态执行:man.cx/fork%282%29
【解决方案2】:

fork 创建两个进程(“父”和“子”)。在您的示例中,每个进程都有不同的 pid 值。子进程的 pid 为 0。父进程的 pid 为子操作系统的 pid(由操作系统分配)。

在您的示例中,每个进程在其内存中都有自己的value。他们确实共享内存(就像您认为他们应该通过您的问题一样。)如果您更改一个进程(if 的第一部分),它将不会反映在第二个进程(if 的第二部分)中如果。)

编辑:解释了 pid 的值。

【讨论】:

  • fork返回的pid为0表示子进程,大于0表示父进程。
  • 为什么子进程的PID是0?为什么父进程不为0,每个子进程从那里递增?
  • @kralco626: man fork 说:“成功时,父进程返回子进程的 PID,子进程返回 0。”
  • @kralco:这样就很容易识别“你”是哪个进程。任何进程都可以通过询问操作系统(getpidgetppid 在 unix 中)轻松获得自己的 PID 或父进程的 PID。
  • @kralco626:这就是fork() 的工作原理。这样,父进程将知道其子进程的确切 pid(> 0),而子进程将知道它是子进程(因为 pid 将返回 0)。请注意,子进程实际上的进程 ID 不是 0,它只是 fork() 向子进程发出信号的方式,它实际上是一个子进程。 (子进程获取自身及其父进程的 PID 也很简单,因为它只有一个父进程,而父进程可能有多个子进程)。
【解决方案3】:

fork 系统调用创建一个新进程作为现有(父)进程的子进程。父进程和子进程都在 fork 语句之后的行继续执行,但是子进程得到了父地址空间的精确副本。

fork 系统调用将新创建进程的进程 id 返回给父进程,将零返回给子进程,因此在这段代码中,子进程将递增其自己的 value 变量副本,而父进程将打印出自己的副本。

您经常会在子程序中看到 fork 后跟一个 exec,以便它用另一个程序替换自己。

【讨论】:

    【解决方案4】:

    当您调用fork 时,它会创建一个进程副本,使两个副本的program counters 在其代码段中的位置相同。因此,当这些副本中的任何一个恢复执行时,两者都将完成对 fork 的调用。

    所以他们两个应该执行相同的。

    但是,fork在子进程中返回0,在父进程中返回子进程的pid

    这就解释了if( pid==0 ) 部分背后的魔力。

    因此,当子进程更改 value 的值时,它实际上会在自己的副本中更改(请记住:进程被复制了,因此数据部分也被复制了)。

    同时,父进程以其旧值 value 执行,即 10。

    即使孩子更改了value 的副本并死亡,父母的副本仍然是 10。

    【讨论】:

      【解决方案5】:

      好吧,fork 产生了一个新进程。它或多或少地复制了当前进程,并且新进程(子进程)和旧进程(父进程)都在代码中的同一点继续进行。但是这里有一个显着的区别(我们感兴趣):对于子进程,fork 返回 0。对于父进程,它返回子进程的进程 ID。

      所以if(pid ==0) 部分对孩子来说是正确的。孩子简单地将 10 添加到 他的 value,然后退出,因为没有进一步的代码。

      else 部分对父级为真(除了极少数情况,fork 返回错误为 -1)。父母只需waits 让孩子退出。但是孩子已经修改了自己的value 副本,父母的副本仍然没有改变,这就是为什么你得到“10”的输出。然后父级也退出。

      【讨论】:

        【解决方案6】:

        fork() 创建一个新进程:它在两个不同的上下文中有两个返回值,因此两条路径都在您的 if 语句中运行。条件句多用于判断你在fork之后运行的是哪个进程。

        【讨论】:

        • 但是只有一个输出行。你能告诉我发生了什么事吗?为什么父进程和子进程不创建和输出语句?
        • 因为在child中,fork返回0。在parent中,fork返回的是child的pid。
        • 哈哈,现在我明白了。进程从 fork() 调用点开始分裂。值为0的子进程和值大于0的父进程。我想我明白了!
        猜你喜欢
        • 1970-01-01
        • 2011-12-31
        • 1970-01-01
        • 2010-11-07
        • 1970-01-01
        • 2011-05-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多