令人困惑的叉系统调用

时间:2010-03-25 04:20:23

标签: c++ c unix fork

我只是检查fork系统调用的行为,我发现它非常令人困惑。 我在一个网站上看到了

Unix将制作父母地址空间的精确副本并将其提供给孩子。因此,父进程和子进程具有单独的地址空间

#include <stdio.h>
#include <sys/types.h>

int main(void)
{
pid_t pid;
char y='Y';
char *ptr;
ptr=&y;
pid = fork();
if (pid == 0)
{
y='Z';
printf(" *** Child process  ***\n");
printf(" Address  is %p\n",ptr);
printf(" char value is %c\n",y);
sleep(5);
}
else
{
sleep(5);
printf("\n ***parent process ***\n",&y);
printf(" Address  is %p\n",ptr);
printf(" char value is %c\n",y);
}
}

上述程序的输出是:

 *** Child process  ***
 Address  is 69002894
 char value is Z

 ***parent process ***
 Address  is 69002894
 char value is Y

所以从上面提到的声明看来,孩子和父母似乎有separet地址空间。这就是为什么char值被单独打印的原因以及为什么我在子进程和父进程中看到变量的地址相同。

请帮我理解这个!

5 个答案:

答案 0 :(得分:7)

基本上,虚拟内存的概念提供了一个过程视图,就好像它是系统的唯一所有者一样。它感觉它可以访问完整的内存。

但实际上,操作系统只给它一个虚拟内存,操作系统使用MMU映射到实际内存。

那么,在你的情况下会发生什么,每个进程(父进程和子进程)都有自己的地址空间。这对两者都是分开的。现在,地址空间指的是虚拟地址空间。

因此,尽管在父级和子级中都存在相同的地址,但这只是虚拟地址。并且每个映射到不同的物理地址。

希望它有所帮助!!

答案 1 :(得分:6)

你是对的。一旦调用fork(),就会存在两个相同的进程。因此,y的地址对于每个进程中的y副本是相同的。两个进程之间的唯一区别是,在一个中,fork()返回0,而在另一个中,它返回了子进程的PID。您的程序正在使用该信息在父级和子级中执行不同的操作,因此您可以获得适当的输出。

在“现实生活中”,操作系统会进行大量优化,以使fork() 真正快速。这意味着实际的物理行为可能不涉及内存空间的完整副本。但是,从逻辑上讲,你可以这样对待它。

答案 2 :(得分:6)

它们具有单独的地址空间 - 这正是允许相同内存地址具有不同值的原因。内存地址仅在进程的上下文中有意义。

答案 3 :(得分:3)

地址221 P Street地址是一条独立的建筑,地址为221 C Street。即使它们具有相同的地址编号,它们的内容也会有所不同。

答案 4 :(得分:1)

您必须将pid替换为ptr。 要获取父级和子级ID,您必须使用pid中的printf(" Address is %p\n",pid);而不是ptrfork()程序运行后分为两部分。一个是孩子,另一个是父母。如果您从fork()之前使用的变量调用地址,您将获得父母和子女的相同结果。