这段C代码是做什么的?

4

我对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);
    }
}

我知道输出结果是“parent: value = 10”。有人知道为什么吗?
谢谢!

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

16

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

在您的示例中,每个进程在其内存中都有自己的value。 它们不共享内存(正如您认为它们应该共享一样)。 如果您更改一个进程(if语句的第一部分),则不会反映在第二个进程(if语句的第二部分)中。

编辑:解释了pid的值。


3
fork返回的pid对于子进程为0,对于父进程则大于0。 - Cătălin Pitiș
为什么子进程的PID是0?为什么父进程不是0,每个子进程都从那里递增呢? - kralco626
@kralco626: man fork显示:“成功时,在父进程中返回子进程的PID,而在子进程中返回0”。 - Bruno
1
@kralco:这样可以轻松地识别出“你”是哪个进程。任何进程都可以通过向操作系统询问(在Unix中使用getpidgetppid)来轻松获取自己的PID或其父进程的PID。 - dmckee --- ex-moderator kitten
4
这就是fork()的工作原理。这样,父进程将知道其子进程的确切pid(>0),而子进程将知道它是子进程(因为pid将返回0)。请注意,子进程并没有真正的进程ID为0,这只是fork()向子进程发出信号表明它实际上是一个子进程的方式。(对于子进程来说,获取自己及其父进程的PID也很简单,因为它只有一个父进程,而一个父进程可能有多个子进程)。 - mipadi
小修改:fork() 不会创建两个进程。它会创建一个新进程,该进程是原始进程的副本... 在几乎每一个方面都是如此。 - Lee-Man

4
关于fork():
  • 如果fork()返回一个负值,说明创建子进程失败。
  • 如果fork()返回0,则表示新创建的子进程。
  • 如果fork()返回一个正值,表示子进程的进程ID,返回给父进程。
因此,在您的情况下,它必须返回大于0的数字,因此该值将保持为10并被打印出来。

非常棒的答案。我正在努力理解这个问题。因此,父进程得到一个大于0的数字,因此进入else部分并打印。子进程得到0。这个子进程做什么?它会创建一个新的进程,从当前行执行还是从代码开头执行? - kralco626
@kralco626 这是父进程的一个副本,从相同的点/状态执行:http://man.cx/fork%282%29 - Bruno

2

fork函数会生成一个新的进程。它几乎完全复制当前进程,新的进程(子进程)和旧的进程(父进程)在代码中的同一点上继续执行。但这里有一个重要的区别(我们感兴趣):对于子进程,fork返回0。对于父进程,则返回子进程的进程ID。

因此,if(pid ==0)部分是子进程的判断条件。子进程简单地将10添加到自己的value中,然后退出,因为没有更多的代码需要执行。

else部分是父进程的判断条件(除非fork返回错误-1)。父进程只需等待子进程退出即可。但是子进程已经修改了value的副本,而父进程的副本仍未被修改,这就是为什么输出结果是“10”的原因。然后,父进程也会退出。


0

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


但是只有一行输出。你能带我了解发生了什么吗?为什么父进程和子进程都没有创建和输出语句? - kralco626
因为在子进程中,fork返回0。在父进程中,fork返回子进程的pid。 - György Andrasek
哈哈,现在我明白了。该过程从fork()调用点分裂。子进程具有值0,父进程具有大于0的值。我想我明白了! - kralco626

0

当你调用fork时,它会创建一个进程的副本,使得这两个副本的程序计数器在它们的代码段中处于相同的位置。因此,当这些副本中的任何一个恢复执行时,两者都将完成对fork的调用。

因此,它们应该执行相同的操作。

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

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

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

同时,父进程使用其旧的value值,即10。

即使在子进程更改其value的副本并死亡后,父进程的副本仍然是10。


0

fork系统调用会创建一个现有进程(父进程)的子进程。父进程和子进程都将在fork语句后的行继续执行,但是子进程将获得与父进程完全相同的地址空间副本。

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

您经常会看到在子进程中使用exec替换自身为另一个程序的fork后跟随的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接