Linux 进程地址空间

Mike! 2024-09-15 17:37:22 阅读 71

在这里插入图片描述

进程地址空间


C/C++对空间的划分

在这里插入图片描述

这个图中展示的内容是在内存吗?

我们称这个区域为地址空间。

图示

在这里插入图片描述

<code>#include<stdio.h>

#include<stdlib.h>

int val_1;//未初始化全局变量

int val_2=100;//已初始化全局变量

int main()

{

printf("code address: %p\n",main);//代码区

const char *str="hello world";//字符常量区code>

printf("str address: %p\n",str);//为什么是str,str就是保存的字符串常量的起始地址code>

printf("val_2 address: %p\n",&val_2);

printf("val_1 address: %p\n",&val_1);

char * mem=(char *)malloc(100);//堆区

printf("heap address: %p\n",mem);

printf("stack address: %p\n",&str);//栈区,局部变量在栈区

}

栈区的地址是向下增长,堆区的地址是向上增长。堆栈相对而升。

static 修饰的变量

为什么用 static 修饰的变量,就不会随着函数调用而被释放?

因为 static 修饰的局部变量,在编译时已经被编译到全局数据区了,所以才不会被释放。

结论

如果变量的地址是物理地址,不可能存在父子进程访问的变量地址相同但是值不同的现象。出现这样的现象称为线性地址或者虚拟地址。所以平时写得 C/C++用的指针,指针里面的地址,绝对都不是物理地址,而是称为虚拟地址。

地址空间

一个可执行程序有代码数据两部分,还会创建进程地址空间。每一个进程都有进程地址空间。

地址空间的概念

概念:所谓的进程地址空间,本质是一个描述进程可视范围的大小。地址空间内一定要存在各种区域划分,对线性地址进行 start 和 end 划分即可。地址空间本质是内核的一个数据结构对象,类似 PCB 一样,地址空间也是要被操作系统管理的:先描述,再组织。

主要组成部分

请添加图片描述

页表

K(键) V(值) 结构

键值为虚拟地址,值为物理地址

当程序运行时,就会根据页表中的虚拟地址来找到对应的物理地址。

写时拷贝的本质:

重新开辟空间,但是在这个过程中,左侧的虚拟地址是不变的,不影响虚拟地址;而是在物理内存中开辟了新空间,将更改的信息存储到这个空间中。所以就出现了虚拟地址相同而值不同的现象。

常见细节问题

总线

CPU 与内存之间的线称为:系统总线

内存和外设之间的线称为:IO 总线

在 32 为计算机中,有 32 位的地址和数据总线。每一根总线只有 0,1 的概念。一共有 2^32 种状态。2^32*1byte=4GB,所以一个 32 位系统最多能装载 4GB 的内存空间。

地址空间究竟是什么?

什么叫做地址空间?

地址总线排列组合形成的地址范围[0,2^32),

如何理解地址空间上的区域划分?

为什么要有进程地址空间?

让所有进程以统一的视角看待内存结构

增加进程虚拟地址空间,可以让我们访问的内存的时候,增加一个转换的过程,在这个转换的过程中,可以对我们的寻址请求进行审查,所以一旦异常访问,我们直接拦截,该请求不会到达物理内存,保护物理内存。

因为有地址空间和页表的存在,可以将进程管理模块和内存管理模块进行解耦合。

页表结构是一个映射表。cr3 寄存器保存的是页表的起始地址(物理地址),这个地址是物理地址

怎么知道进程的代码数据在不在内存?

操作系统对大文件可以实现分批加载

惰性加载

操作系统对进程的加载策略为惰性加载的方式,

缺页中断

在页表中有一列为对应的代码和数据是否已经被加载到内存,如果显示不在,操作系统会触发缺页中断,操作系统会重新申请内存。(写时拷贝就是一种缺页中断)

进程被创建的时候,是先创建内核数据结构呢?还是先加载对应的可执行程序呢?

先创建内核数据结构


在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。