C 地址';s、 fork()后面的值和指针
我正在研究一个问题,在C中检查C 地址';s、 fork()后面的值和指针,c,fork,parent-child,memory-address,virtual-memory,C,Fork,Parent Child,Memory Address,Virtual Memory,我正在研究一个问题,在C中检查fork()调用前后的值和地址。我的方法是显示变量值和地址,假设在fork()之后看到地址的差异。令我大吃一惊的是,上述变量保持不变 我的问题是为什么它们是一样的?如果我更改子对象中的变量,会发生什么情况?父母和孩子都会改变吗?如果不是,当父级和子级的地址相同时,如何更改该地址中的值 代码(供参考): 地址相同,但引用的内存不同。每个进程都有自己的地址空间。在现代系统上,这是通过虚拟内存实现的——在较旧的系统上,它可以通过段基寻址或简单交换(卸载一个进程并将另一个进
fork()
调用前后的值和地址。我的方法是显示变量值和地址,假设在fork()之后看到地址的差异。令我大吃一惊的是,上述变量保持不变
我的问题是为什么它们是一样的?如果我更改子对象中的变量,会发生什么情况?父母和孩子都会改变吗?如果不是,当父级和子级的地址相同时,如何更改该地址中的值
代码(供参考):
地址相同,但引用的内存不同。每个进程都有自己的地址空间。在现代系统上,这是通过虚拟内存实现的——在较旧的系统上,它可以通过段基寻址或简单交换(卸载一个进程并将另一个进程加载到相同的内存区域)来实现。子进程具有父地址空间的副本。在现代系统中,地址是虚拟化的,因此任何特定的指针地址都可以在一个进程中映射到与另一个进程不同的物理地址
如果我更改子对象中的变量,会发生什么情况?父母和孩子都会改变吗
子项有自己的变量副本,因此更改子项中的变量不会影响父项中变量的值
如果没有,当父级和子级的地址相同时,如何更改该地址中的值
这是由于两个进程中的相同地址映射到不同的物理地址。它们怎么可能发生变化?想想看。这是不可能的。经过进一步研究,我期望的是一个物理内存地址,而显示的是虚拟内存地址。不可能在同一物理地址中有两个变量,但可以从一个虚拟内存地址引用两个虚拟内存地址。是否可以显示物理内存地址?@Andrewrici通常不-通常,您不/不应该关心代码/数据所在的物理地址,因为这真的没什么区别。此外,地址可能会随着程序的运行而改变-内存可以被分页进出。很可能在分叉之后,它们将具有相同的物理地址。在一个或另一个程序修改内容之前,不需要复制。(因此,物理地址在写入时会改变!)@Andrewrici,在davmac发表的评论中,物理地址甚至可以在程序运行时改变,甚至根本不存在。虚拟内存可以调出到磁盘,然后实际的虚拟地址在被引用时只会遇到一个页面错误,内核将其调出(在一个几乎可以确定的不同物理地址),然后您就可以再次获得它。请注意,fork()通常是使用写页上的复制来实现的,即,只要没有对该页的写操作,这些地址将引用相同的内存。但从概念上讲,它不是相同的内存。写时复制是一个实现细节。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
int status;
pid_t pid;
int a = 123456;
float b = 123.456;
char c = 'Z';
int *e;
e=&a;
//Retriving address's
void *ap=&a, *bp=&b, *cp=&c, *ep=&e;
printf("Parent Before Fork:\n");
printf("Integer a: \tvalue = %d, \taddress = %p\n", a, ap);
printf("Float b: \tvalue = %f, \taddress = %p\n", b, bp);
printf("Char c: \tvalue = %c, \t\taddress = %p\n", c, cp);
printf("Pointer e: \tvalue = %p, address = %p\n", e, ep);
pid = fork();
if(pid > 0)
{
pid = wait(&status);
printf("\nParent After Fork:\n");
printf("Integer a: \tvalue = %d, \taddress = %p\n", a, ap);
printf("Float b: \tvalue = %f, \taddress = %p\n", b, bp);
printf("Char c: \tvalue = %c, \t\taddress = %p\n", c, cp);
printf("Pointer e: \tvalue = %p, address = %p\n", e, ep);
sleep(1);
}
else if(pid == 0)
{
printf("\nChild After Fork:\n");
printf("Integer a: \tvalue = %d, \taddress = %p\n", a, ap);
printf("Float b: \tvalue = %f, \taddress = %p\n", b, bp);
printf("Char c: \tvalue = %c, \t\taddress = %p\n", c, cp);
printf("Pointer e: \tvalue = %p, address = %p\n", e, ep);
}
else
printf("fork() did not work");
return 0;
}
Parent Before Fork:
Integer a: value = 123456, address = 0x7fff8b8e378c
Float b: value = 123.456001, address = 0x7fff8b8e3790
Char c: value = Z, address = 0x7fff8b8e3787
Pointer e: value = 0x7fff8b8e378c, address = 0x7fff8b8e3798
Child After Fork:
Integer a: value = 123456, address = 0x7fff8b8e378c
Float b: value = 123.456001, address = 0x7fff8b8e3790
Char c: value = Z, address = 0x7fff8b8e3787
Pointer e: value = 0x7fff8b8e378c, address = 0x7fff8b8e3798
Parent After Fork:
Integer a: value = 123456, address = 0x7fff8b8e378c
Float b: value = 123.456001, address = 0x7fff8b8e3790
Char c: value = Z, address = 0x7fff8b8e3787
Pointer e: value = 0x7fff8b8e378c, address = 0x7fff8b8e3798