Linux:程序的地址空间

程序地址空间

我们在学习C语言的时候,曾经在对函数调用学习的时候,曾经提到过一个所谓的内存空间,也就是程序地址空间。我们在对程序地址空间学习的时候,了解了在程序地址空间内,从下自上分别是代码区、只读常量区、已初始化全局数据区、未初始化全局数据区、堆区、栈区。
这里写图片描述

我们知道fork()函数可以创建子进程,而fork()之后产生的子进程,与其父进程共享代码,并且数据各自私有一份,当任意一个写入数据时,发生写时拷贝。

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

int value = 0;

int main()
{
    pid_t id = fork();//利用fork产生子进程后的返回值来让父子执行不同的代码
    if(id < 0)
    {
        perror("fork");
        return 0;
    }
    else if(id == 0)
    {//子进程
        printf("child[%d] : %d : %p\n",getpid(),value,&value);
    }
    else
    {//父进程
        printf("father[%d] : %d : %p\n",getpid(),value,&value);
    }
    sleep(1);
    return 0;
}

这里写图片描述

我们可以看到,子进程与父进程中value的地址是相同的,也就是说他们确实是共用一块代码,我们对这个代码稍加改动。

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

int value = 0;

int main()
{
    pid_t id = fork();//利用fork产生子进程后的返回值来让父子执行不同的代码
    if(id < 0)
    {
        perror("fork");
        return 0;
    }
    else if(id == 0)
    {//子进程
        value = 100;
        printf("child[%d] : %d : %p\n",getpid(),value,&value);
    }
    else
    {//父进程
        printf("father[%d] : %d : %p\n",getpid(),value,&value);
    }
    sleep(1);
    return 0;
}

这里写图片描述

我们发现,这个时候子进程跟父进程两个的value是同一块地址,但是为什么其value的值不一样呢?按照我们的程序地址空间来说,同一个地址内的内容应该是一样的呀,怎么会这样呢?

这里写图片描述

其实我们的程序地址空间是进程(PCB)task_struct结构体内的一个成员,而这个程序地址空间上面的内容其实都是虚拟的,也就是说它上面所说的内存并不是真正的物理内存。而真正的物理内存需要程序地址空间这个虚拟的内存通过页表来映射。
当我们调用fork()函数的时候,父子进程在物理地址上共用一份代码,并且数据各自私有,但是其对应的虚拟地址空间的内容是一样的。如下图:
这里写图片描述
所以当我们子进程的value的值时,父进程与子进程看似value地址一样,实则在物理内存上并不一致。所以其互不影响。

其实计算机如此设计目的就是为了更好的保护物理内存,防止物理内存被破坏以及侵占。


欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值