进程地址空间

image-20230110224909585

进程地址空间

子进程和父进程共享同一块空间吗?

咱先做一个小测试,创建一个子进程,让子进程和父进程打印各自的进程id和父进程id,打印相同的全局变量值global_val和其地址

image-20230107111847156

运行后可以看到,子进程id为5738,父进程id为5739,前五秒global_val的值为100,地址为0x60105c,然后子进程把global_val改变了,然后子进程打印global_val的值为300,父进程打印global_val还是100,但是子进程和父进程打印global_val的地址是相同的!不同的值相同的地址!

image-20230107111959879

那么可以推断这个全局变量的地址不是物理地址而是虚拟地址!

那么虚拟地址是啥?虚拟地址和进程地址空间又有什么关系?

感性认识进程地址空间

通过小故事感性的认识进程地址空间

这里有个大富翁叫马海他有十个亿人民币,他有三个私生子分别叫小帅,小黑,小白。三个私生子分别互相不认识,都以为是马海的独生子而且都知道老爸很有钱。

一天马海给作为程序员的小帅画饼:如果他能在阿里巴巴努力工作,努力成为P8高级专家,等马天死后就把10个亿分到小帅麾下。这天马海也同时给另外两个私生子小黑和小白画饼:等他死后那么财产就归他们各自所有。

然而每次小帅缺钱都不会叫他老爸给十亿,比如要买新电脑了叫他爸给1万,要买车了要给50万,但都不会开口要十亿。另外两个私生子也一样。像老爸要钱不会要十亿这么多,因为他们各自知道,这老头子死后那十个亿都属于他们各自。

相应的:那大富翁就是操作系统,他的私生子就是进程(彼此不知道对方的存在),大富翁给私生子的零花钱就是进程向操作系统申请,操作系统给进程分配的内存或者对象空间;而大富翁给私生子画的大饼相应的是进程地址空间,就是操作系统给进程画的大饼(进程会认为自己独占操作系统的资源事实上并不是)

image-20230108121049898

那怎么画饼呢?先描述,再组织! 进程要被管理,那么大饼也要被管理(画啥饼?画多大?)即进程地址空间也要被管理。而在操作系统中,地址空间的本质是内核的一种数据结构:mm_struct

系统上的进程地址空间

让我们再回顾当时学的内存空间

image-20230110173435801

地址空间的描述的基本空间大小是字节,32位下有2^32方个地址,相当于4GB大小的空间范围,每一个字节都要有唯一的地址(即空间地址只需要保证唯一性即可),这些空间地址是虚拟地址。每个地址都是按照从低地址到高地址排列,所以虚拟地址又称线性地址(在Linux系统下也称逻辑地址)。

每个mm_struct (区域)都有一个start指针(区域起始地址)和一个end指针(区域结束地址)两个指针之间有无数个地址。

heap和stack的区域调整,本质上是通过修改各个区域的start和end—即空间的扩大和缩小

mm_struct 的地址在task_struct(pcb)中。磁盘把程序的数据和代码加载到内存中,此时该进程在内存中有了物理地址。虚拟地址通过页表找到内存中的代码和数据。

image-20230110192259574

相应的,跟上面感性的理解一样,son1和son2看到的是虚拟内存(画的饼),虚拟内存通过页表和物理内存联系,压根就看不到物理内存(十个亿)

image-20230110185936183

为什么要存在地址空间?

1.如果让进程直接访问物理内存,万一进程越界非法操作,那么物理内存中的数据就会被非法篡改,非常的不安全。所以要存在一个地址空间,地址空间通过页表映射于物理内存联系,如果进程非法操作,操作系统会在页表处直接拦截!

2.地址空间的存在,可以更方便的进行进程和进程数据代码的解耦,保证了进程独立性。

现在能更加清晰的解释为什么父进程和子进程共享同一个空间时,子进程改变了变量,而指向的空间和父进程是一样的。父进程在创建子进程时,会把大部分数据和地址传递给子进程。子进程和父进程一样,地址空间通过页表找到物理空间上的数据,但是当子进程想要改变物理内存上的数据时,操作系统会把子进程本来和父进程共用的空间上的数据和代码拷贝到另外一个空间上,然后子进程在新的空间上修改数据。即任何一个进程尝试写入,操作系统先进行 进程数据拷贝,让不同的进程数据进行分离,更改页表映射,然后再让进程进行修改—写实拷贝。也也是为了保证进程的独立性。

3.让进程以统一的视角来看到进程对应的代码和数据等各个区域,方便使用编译器也已统一的视角来进行编译代码。

在编译器中也遵循按照虚拟地址空间的方式进行我们的代码和数据编址,然后加载到内存中,代码和数据也有了物理地址,然后通过页表映射到进程地址空间上,这样就完成了逻辑地址(编译器中的虚拟地址)—物理地址—虚拟地址的对应,这样就方便我们调用。比如需要编译编译器中的main函数时,cpu就找到编译器中的main函数start指针(区域起始地址)。

区域划分

0-3G是用户空间,也就是前面提到的进程地址空间及其他,3-4G是内核空间。

image-20230110224418472

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值