linux进程控制系列(3)父子进程变量虚拟内存地址相同但变量值不同的问题

    首先,我们来看一个实例:

process_fork3.c

/*
 * process_fork3.c
 *
 *  Created on: 2016-11-13
 *      Author: river
 */
/*
 * process_fork.c
 *
 *  Created on: 2016-11-11
 *      Author: river
 */

#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

//全局变量
int g_v = 30;


int main()
{

    int a_v = 30;//局部变量
    static int s_v = 30;//静态变量

    pid_t pid;
    pid = fork();//创建子进程
    //在fork之后会运行2个进程(父进程、子进程)
    if(pid < 0)
    {
        perror("fork error");
    }
    else if(pid > 0)
    {//父进程(在父进程中fork返回的是子进程的pid)
     //父进程执行的代码...
        g_v = 40;
        a_v = 40;
        s_v = 40;

        printf("I am parent process pid is %d\n", getpid());
        printf("g_v: %p, a_v: %p, s_v: %p\n\n\n", &g_v, &a_v, &s_v);
    }
    else
    {//子进程(在子进程中fork返回的是0)
     //子进程执行的代码...
        printf("kkkpid: %d, g_v:%d, a_v:%d, s_v:%d\n", getpid(), g_v, a_v, s_v);//父子进程都执行
        g_v = 50;
        a_v = 50;
        s_v = 50;

        printf("I am child process pid is %d\n", getpid());
        printf("g_v: %p, a_v: %p, s_v: %p\n\n\n", &g_v, &a_v, &s_v);
    }
   

    printf("pid: %d, g_v:%d, a_v:%d, s_v:%d\n\n\n", getpid(), g_v, a_v, s_v);//父子进程都执行

    sleep(1);//睡眠1s使得父子进程可以交替运行

    exit(0);
}

    上面的例子,我们定义3个变量,分别是全局变量、局部变量、静态变量,并都赋予初始值30,在父进程中都修改为40,并打印三个变量的地址,在子进程中都修改为50,并打印三个变量的地址,最后父子进程分别打印三个变量的值。

程序运行输出结果为:

I am parent process pid is 21268
g_v: 0x804a034, a_v: 0xbf8e1528, s_v: 0x804a038



pid: 21273, g_v:30, a_v:30, s_v:30
pid: 21268, g_v:40, a_v:40, s_v:40


I am child process pid is 21273
g_v: 0x804a034, a_v: 0xbf8e1528, s_v: 0x804a038


pid: 21273, g_v:50, a_v:50, s_v:50



     从上面的输出结果我们可以看到父进程的ID是21268,子进程的ID是21273,我们用绿色标示了父进程的输出信息,蓝色标示了子进程的输出信息。

      对于pid: 21273, g_v:30, a_v:30, s_v:30这一句的解释是 在程序运行开始我们将三个变量都初始化为30,因此子进程在没有对三个变量进行修改之前,我们打印的三个变量的值是从父进程中继承而来的数值(注意父进程是在fork之后对三个变量修改为40的,所以父进程拷贝到子进程中的三个变量的值仍然是父进程初始化为30的值),这也就验证了上一篇文章中提到的子进程会遗留父进程中的数据。

      我们会看到这样一个现象:

      I am parent process pid is 21268 

      g_v: 0x804a034, a_v: 0xbf8e1528, s_v: 0x804a038

          I am child process pid is 21273
      g_v: 0x804a034, a_v: 0xbf8e1528, s_v: 0x804a038

          父进程变量的地址与子进程变量的地址是一样的,也就是说不同的进程的变量却有相同的虚拟地址(注:程序中变量的地址都是虚拟地址,而非物理地址)。原因是内核会为每个进程分配4G的虚拟地址空间,这4G的虚拟地址空间地址分布都是一样的,由于子进程虚拟地址空间的数据都是从父进程中拷贝而来的,都是一样的,因此相同的数据在4G的虚拟地址空间中的分布也是一样的。那为什么相同的虚拟地址(变量地址)最终会得到不同的变量值呢?原因是虽然虚拟地址分布是一样的,但是由于相同的虚拟地址映射到不同的物理地址,所以我们才会得到不同的变量值。

     下面的示图描了这一点:

                    

    从上图可以看到,虽然父进程与子进程中三个变量虚拟地址是一样的,但是映射到不同的物理地址就得到了不同的数值。



 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洪流之源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值