【发布时间】:2010-03-25 04:20:22
【问题描述】:
我只是检查 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
所以从上面提到的语句看来,子进程和父进程似乎有单独的地址空间。这就是为什么单独打印 char 值以及为什么我在子进程和父进程中看到变量的地址相同的原因。?
请帮助我理解这一点!
【问题讨论】:
-
变量名称仅在某些特定语言的编译时存在。在运行时,您的代码使用精确地址(对于堆栈,它使用某个寄存器的偏移量,并且在程序映射到内存后内存指针被重新定位)。同样,正如您的示例所述 - 就在分叉当前进程之前,您将指针存储在某个地方(它甚至可以是一些外部存储)。因此,如果 fork() 会导致内存布局发生变化 - 从该系统调用返回后,您的程序将无法进一步工作。
-
答案是正确的,但在您的实际示例中,还有另一个问题。您将 Y 的地址存储在分叉之前的 ptr 中,因此 ptr 包含“69002894”。在 fork 之后, ptr 仍然会在父进程和子进程中包含该值,即使 Y 的地址在两个进程之一中会发生变化。为了正确起见,您必须在 printf 语句中打印 &Y。
-
@laurent 在 fork ptr 之后也将被复制到子进程。这意味着孩子和父母将有两个不同的ptr。请按照您自己在 printf 中的建议更改语句进行检查。您将得到相同的结果。
-
是的,由于答案中提到的原因(虚拟地址空间),我知道您会得到相同的结果。我的意思是,IF y 的地址在孩子的进程中会有所不同(每个人都同意不是这种情况),PTR 的值仍然是 Y 的地址父进程而不是子进程中 Y 的地址。所以你不会在你的 printfs 中看到差异。