依然写时复制的疑惑
昨天发帖问的关于写时复制的问题,大体上有了一定了解。但是我做了实验,发现不对啊:在子进程里面写变量之后查看变量地址,发现地址还是跟父进程一样。
结果:
sqNum1[g] in child is 161970448
sqNum1[g] in parent is 161970448
代码:
if((ntid[g]=fork())<0)
{
printf("can't creat new process\n");
exit(1);
}
else
{
signal(SIGCHLD,SIG_IGN);
if(ntid[g]==0)
{
//sqNum1[g]++;//操作数据或者不操作
sqCHLD=sqNum1[g]; //读
if(signal(SIGUSR1,sig_usr_sq)==SIG_ERR)
printf("can't catch SIGUSR1\n");
sqCHLD_pro=sqCHLD;
while(1)
{
printf("sqNum1[g] in child is %u\n",&sqNum1[g]); //查看子进程中地址
sleep(2*time_to_alive/1000);
if(sqCHLD==sqCHLD_pro)
printf("goose %u %ubreak\n",g,sqCHLD);
else
sqCHLD_pro=sqCHLD;
}
}
printf("sqNum1[g] in parent is %u\n",&sqNum1[g]);//查看父进程中的地址
//printf("this is in process %u\n",g);
}
}
[解决办法]
只看代码的话
if(ntid[g]==0)这个没有对应的else
printf("sqNum1[g] in parent is %u\n",&sqNum1[g]);这个父子进程都会运行到的
[解决办法]
每个进程都有自己独立的虚拟地址.所以虽然都是
sqNum1[g] in child is 161970448
但是,他们对应的不是同一个物理地址.(操作系统掌控着)
这是老师上课时讲的一个fork的经典例子.
[解决办法]
大意就是 打印的地址跟fork没什么关系,证明不了什么.
地址只是虚拟地址.每个进程都可以有这样一个地址.
内核默认配置例如0~3G内存为用户地址空间,则每个进程都可以有0~3G这样一段虚拟内存.
内存管理/映射 负责管理虚拟内存和物理内存的对应关系.
我看你前面的帖子,好像是关于进程间通讯的知识.父子进程要交流就乖乖的使用一些进程间通讯的东西.
他们是专门设计用来处理这样的情况的.
要知道的更明了还是得阅读kernel源代码.这个就复杂一些了.整个内核所有进程几乎都是fork出来的.涉及到很多内容.
[解决办法]
地址一样是因为本来就是父进程的副本,在每个进程的4GB逻辑地址空间中布局的内存一样也没什么大惊小怪的。
但你改子进程中的变量,父进程是不会变得,除非有共享内存。