冯诺依曼体系结构
搞定操作系统
搞懂什么是进程
进程状态和创建
环境变量
程序地址空间
✅1.图解
展示4G运行内存下的程序地址空间
✅ 2.什么是程序
✔2.1 定义
- 程序是一堆
死代码
,保存在程序文件中,编译器在编译程序生成可执行文件时,就会对每一条指令,每一个数据,进行一个地址编号✔2.2过程
- 当程序运行的时候,就会将指令以及数据放到指定位置的内存地址位置
- cpu就会根据地址偏移逐步去执行指令,以及找到对用的数据进行处理
- 程序运行之后才会占据内存,因此程序地址空间通常被称为进程地址空间
✅3.什么是地址
- 内存地址,队内存以字节为存储单位的一个编号, 通过地址就能找到具体对应的内存单元
✅4.什么是程序地址空间
- 程序地址空间,就是操作系统为进程使用mm_struct结构体描述的一个
虚拟
的地址空间
程序地址空间通常被称为进程地址空间
进程地址空间是什么
✅1.问题
- 如果真的将物理内存分成了不同的区域,代码段存放的是代码,权限是只读的,不能修改的
- 如果物理内存有一段不可修改,那数据是怎么放进去的?
✅2.分析
- 我们知道一个内存地址只能指向一个唯一的内存单元,一个内存单元只能存储一个数据
- 其实进程中所访问的地址都是虚拟地址,一个假地址,并非物理内存的地址
- 我们所说的程序地址空间,实际上也是一个虚拟的地址空间
- 是操作系统为进程通过一个mm_struct结构体所描述的一个假的地址空间
mm_struct (task_size, start_code, end_code)
,通过大小以及区域的编号描述
✅3.结论
- 原来我们所说的地址空间是一个虚拟的地址空间,只是一堆地址编号的描述(
并非物理内存地址
)
✅4.图解
4.1为什么需要虚拟内存地址
✅1.提出问题
- 为什么操作系统不让进程直接访问物理内存,而是弄了一个虚拟地址空间,让进程访问虚拟地址呢?进程直接访问物理内存,有什么不好?
✅2.分析
✔ 没有虚拟地址有什么坏处
1.程序在编译时,编译器就会给指令和数据进行地址编号,但是如果某个地址内存已经被占用,则程序就运行不起来了
2.编译器的地址管理麻烦,无法动态获知拿快内存是否被使用,也无法进行代码以及数据的地址赋值
3.如果让进程直接访问物理内存,有一个野指针的话,在操作的时候可能就把其他进程的数据改变了,即无法进行内存访问控制
4.程序加载通常需要使用一块连续的内存空间,内存利用率很低✔有虚拟内存有什么好处
1.通过虚拟地址空间映射到物理内存上进行数据存储,可实现数据在物理内存上的离散式存储,提高内存的利用率
2.每个进程都有自己的虚拟内存空间,因此对于每个进程来说,都会拥有自己的一块连续的空间使用
进程中访问的都是虚拟地址,如何通过虚拟地址找到物理内存呢?
操作系统中内存管理方式
✅1.分段式
✔方法
- 将虚拟地址的组成分为
段号
+段内偏移量
(比如全局数据段有很多变量,他们的段号都是一样的,也就意味着段的起始位置一样,但是每个变量的偏移量不同)
- 通过段号对应的物理内存段起始地址以及虚拟地址中的偏移量组成一个完整的物理内存,找到对应的物理内存单元
✔图解
✔优点
- 对编译器的地址管理比较友好
✔缺点
- 没有解决数据连续存储内存利用率低的问题,因为一个段管理了很多变量数据,这些变量就都从同一个起始位置进行偏移,也就在物理地址中使用了连续的地址空间
- 分段号式管理中,同一个段内数据都使用了连续的地址空间,每个段之间不用连续,但是段内是连续的
✅2.分页式
✔方法
因为通常物理块比较小,并且不要求同一个进程的多个数据必须在同一块内,因此分页式腾空出世
页表会在进行内存访问的时候进行内存访问控制,判断是否有权限
页表放的是页表项,每个页表项保存的都是一个虚拟内存页与对应物理内存块的映射关系
✔图解
✔分页式管理的优点:
- 实现数据离散式存储,提高内存利用率,并且通过页表进行内存访问控制
- 实现了数据在物理内存中的离散式存储
✔计算
- 在32为系统中,若页表大小是4096,则页表项有1024*1024个,也就是2^20
- 虚拟地址中页号占据虚拟地址的高20 位
分页式与分段式各有优缺点,所以我们用段页式
✅3.段页式
- 综合了 分段式 和分页式,将内存进行分段,在每个段内采用分页管理
✔图解