我引用“当进程使用fork()调用创建一个新进程时,只有父进程和新分叉的子进程之间共享共享内存段 . 堆栈和堆的副本是为新创建的进程”从Silberschatz的“操作系统概念”解决方案 .
但是当我尝试这个程序的时候
#include <stdio.h>
#include <sys/types.h>
#define MAX_COUNT 200
void ChildProcess(void); /* child process prototype */
void ParentProcess(void); /* parent process prototype */
void main(void)
{
pid_t pid;
char * x=(char *)malloc(10);
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
printf("the address is %p\n",x);
}
void ChildProcess(void)
{
printf(" *** Child process ***\n");
}
void ParentProcess(void)
{
printf("*** Parent*****\n");
}
结果如下:
*** Parent*****
the address is 0x1370010
*** Child process ***
the address is 0x1370010
父和子两者都打印堆中的相同地址 .
谁能解释我这里的矛盾 . 请清楚说明父母和孩子在内存空间中共享的所有内容 .
6 回答
当内核
fork()
是进程时,复制的内存信息会继承相同的地址信息,因为堆被有效地按原样复制 . 如果地址不同,您将如何更新自定义结构中的指针?内核对该信息一无所知,因此这些指针将无效 . 因此,物理地址可能会发生变化(实际上即使在可执行文件的生命周期内也经常会发生变化,即使没有fork()
ing,但逻辑上也是如此地址保持不变 .从另一个线程引用自己 .
另外,要理解为什么这些程序似乎使用相同的内存空间(事实并非如此),我想引用“操作系统:原理与实践”一书的一部分 .
所以这些虚拟地址是物理地址的翻译,并不代表相同的物理内存空间,如果我们编译并运行多次显示静态变量方向的程序,我们可以做一个更实际的测试示例,比如这个程序 .
如果我们直接处理物理内存,就不可能在两个不同的程序中获得相同的内存地址 .
多次运行程序得到的结果是......
是的,两个进程对此变量使用相同的地址,但这些地址由不同的进程使用,因此不在同一个virtual address space中 .
这意味着地址是相同的,但它们并不指向相同的物理内存 . 您应该阅读有关虚拟内存的更多信息以了解这一点
您可能正在使用虚拟内存的操作系统上运行程序 . 在
fork()
调用之后,父级和子级具有单独的地址空间,因此地址0x1370010
未指向同一位置 . 如果一个进程写入*x
,则另一个进程将看不到更改 . (实际上,这些内存可能是相同的内存页面,甚至是交换文件中的相同块,直到它处理自己的副本为止 . )地址是相同的,但地址空间不是 . 每个进程都有自己的地址空间,因此父进程0x1370010与子进程0x1370010不同 .
在这两种情况下,是的地址是相同的 . 但是如果你在子进程和父进程中为x分配不同的值,然后还打印x的值和x的地址,你将得到你的答案 .
输出将是:
现在,您可以看到值不同但地址相同 . 所以这个过程的地址空间是不同的 . 这些地址不是实际地址而是逻辑地址,因此对于不同的进程可能相同 .