令人困惑的叉系统调用

Vij*_*jay 4 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);
}
}
Run Code Online (Sandbox Code Playgroud)

上述程序的输出是:

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

 ***parent process ***
 Address  is 69002894
 char value is Y
Run Code Online (Sandbox Code Playgroud)

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

请帮我理解这个!

小智 7

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

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

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

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

希望能帮助到你!!


Car*_*rum 6

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

在"现实生活",操作系统做了很多的优化,使fork() 快.这意味着实际的物理行为可能不涉及内存空间的完整副本.但是,从逻辑上讲,您可以这样对待它.

  • @benjamin,是的,它们是不同的进程,因此每个进程都有自己独立的虚拟内存空间.一旦`fork()`返回,它们就完全独立了. (3认同)
  • "单独的地址空间"意味着一个进程中的给定地址指的是来自另一个进程中的相同地址的单独的存储器位.这就是你的例子中的地址69002894能够同时存储"X"和"Y" - "进程A中的地址69002894"是与"进程B中的地址69002894"不同的位置. (2认同)

Bil*_*eal 6

它们具有单独的地址空间 - 这正是为什么允许相同的存储器地址具有不同的值.内存地址仅在进程的上下文中有意义.