原文地址:第三章 内存管理——王道操作系统 – Beatless
目录
一、内存管理概念
内存的基础知识
内存:可存放数据。程序执行前需要先放到内存中才能被CPU处理。
存储单元:由若干存储元件组成,每个存储元件存储一位二进制数。
① 若计算机按照字节编址,每个存储单元的大小为1字节,1B = 8bit;
② 若计算机按字编址,则每个存储单元的大小为一个字,字长由题目给出16位或32位等。
代码被翻译成指令,指令由操作码与地址码组成:指令 = 操作码 + 地址码。
有些指令可能没有地址码,比如停机指令
逻辑地址:指程序运行过程中使用的地址,也称为虚拟地址(Virtual Address)。它由CPU生成,用于访问内存中的数据。对于32位系统,逻辑地址的范围为[0, 2^32 – 1]
进程在运行时看到和使用的都是逻辑地址;不同进程可以有相同的逻辑地址,可以映射到内存的不同位置。
(1)逻辑地址的大小和位数取决于CPU的架构和操作系统的设计,通常是一个定长的二进制数值。
(2)在执行指令时,CPU通过将逻辑地址转化为物理地址来获取数据。
物理地址:指内存中实际的地址,也称实地址(Real Address)。
物理地址表示内存模块中每个存储单元(通常是字节)的唯一标识符,因此具有唯一性,且直接与内存相关联。
在内存管理中,操作系统根据自己的算法,将逻辑地址转化为物理地址,使得程序能够正常读取内存中的数据和向内存写入数据。
内存管理的主要功能:
① 内存空间的分配与回收;② 地址转换;③ 内存空间的扩充;④ 内存共享;⑤ 存储保护
1、装入的三种方式
(1)绝对装入:在编译的时候,如果知道程序将要放到内存的哪个位置(1、编译或汇编时给出;2、程序员直接赋予),编译程序将产生绝对地址的目标代码。装入程序按照装入模块中的地址,将程序和数据装入内存。
程序中使用的绝对地址,可在编译或汇编时给出,也可以由程序员直接赋予。而通常情况下采用的是符合地址,汇编或编译的时候转换为绝对地址。
(2)静态重定位(可重定位装入):编译、链接后的装入模块的地址都是从0开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址。可根据当前内存的情况,将装入模块装入到内存的合适位置,装入时对地址重定位,将逻辑地址转化为物理地址。(地址变换是在装入时完成的)
当一个作业装入内存时,必须分配给它要求的全部内存空间,若没有足够的内存空间,则无法装入。作业一旦进入内存空间,整个运行期间就不能再内存中移动,也不能再申请新的内存空间。
(3)动态重定位(动态运行时装入):编译、链接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转化为物理地址,而是把地址转换推迟到程序真正要执行的时候才进行。因此装入内存后所有的地址依旧是逻辑地址。这种需要一个重定位寄存器的支持。
重定位寄存器:存放程序在内存中的起始位置。
优点:可将程序分配到不连续的存储区;在程序运行之前只需要装入它的部分代码即可投入运行,然后再程序运行期间,根据需要再动态地申请分配内存;便于程序段的共享。
注意:(1)、(2)装入内存后都是物理地址,而(3)装入内存后依旧是逻辑地址。
2、链接的三种方式
(1)静态链接:在程序运行之前,先将各目标模块及它们所需的库函数链接成一个完整的可执行文件,之后不再拆开。
需要解决两个问题:
① 修改相对地址。编译后所有目标模块都是从0开始的相对地址,当链接成一个装入模块时需要修改相对地址。
② 变换外部调用符号。将每个模块中所用的外部调用符号都变换为相对地址。
(2)装入时动态链接:将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的方式。
优点:便于修改和更新,便于实现对目标模块的共享。
(3)运行时动态链接:在程序执行时需要用到该模块时,才对它进行链接。
优点:加快程序的装入过程,还可以节省内存空间。
3、进程的内存映像
概念:不同于存在硬盘上的可执行文件,当一个程序调入运行的时候,就构成了进程映像。包含:
(1)代码段:即一个程序的二进制代码部分,代码段只读,可被多个进程共享。
(2)数据段:包含全局变量和局部变量。
(3)进程控制块(PCB):存放于系统区,OS通过PCB来控制和管理进程。
(4)堆:用来存放动态分配的变量,通过调用malloc函数动态地向高地址分配空间。
(5)栈:用来实现函数调用,从用户空间往低地址增长。
代码段和数据段在调入内存中时就指定了大小,而堆和栈会动态地扩展和收缩。
4、内存共享
内存共享的实现:① 共享存储的进程通信;②