操作系统—内存管理(1)
目录
1.程序的链接与装入
2.逻辑地址与物理地址
3.进程的内存映像
4.内存分配与回收
1.程序的链接与装入
创建进程首先要将程序和数据装入内存。将用户源程序变为可在内存中执行的程序,通常需要以下几个步骤:
1)编译。由编译程序将用户源代码编译成若干目标模块。
2)链接。由链接程序将编译后形成的一组目标模块,以及它们所需的库函数链接在一起,形成一个完整的装入模块。
3)装入。由装入程序将装入模块装入内存运行。
将一个装入模块装入内存时,有以下三种装入方式:
(1)绝对装入。绝对装入方式只适用于单道程序环境。在编译时,若知道程序将放到内存的哪个位置,则编译程序将产生绝对地址的目标代码。装入程序按照装入模块的地址,将程序和数据装入内存。由于程序中的逻辑地址与实际内存地址完全相同,因此不需对程序和数据的地址进行修改。
(2)可重定位装入。经过编译、链接后的装入模块的始址(起始地址)通常都从0开始,程序中使用的指令和数据地址都是相对于始址的,此时应采用可重定位装入方式。根据内存的当前情况,将装入模块装入内存的适当位置。
(3)动态运行时装入。动态运行时装入也称动态重定位。程序若要在内存中发生移动,则要采用动态的装入方式。装入程序将装入模块装入内存后,并不会立即将装入模块中的相对地址转换为绝对地址,而是将这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址均为相对地址。这种方式需要一个重定位寄存器(存放装入模块的起始位置)的支持。
当对目标模块进行链接时,根据链接的时间不同,分为三种链接方式,静态链接、装入时动态链接、运行时动态链接。
2.逻辑地址与物理地址
编译后,每个目标模块都从0号单元开始编址,这称为该目标模块的相对地址(或逻辑地址)。
当链接程序将各个模块链接成一个完整的可执行目标程序时,链接程序顺序依次按各个模块的相对地址构成统一的从0号单元开始编址的逻辑地址空间(或虚拟地址空间),对于32位系统,逻辑地址空间的范围为0 ~ 2^32 - 1。进程在运行时,看到和使用的地址都是逻辑地址。用户程序和程序员只需知道逻辑地址,而内存管理的具体机制则是完全透明的。不同进程可以有相同的逻辑地址,因为这些相同的逻辑地址可以映射到主存的不同位置。
物理地址空间是指内存中物理单元的集合,它是地址转换的最终地址,进程在运行时执行指令和访问数据,最后都要通过物理地址从主存中存取。当装入程序将可执行代码装入内存时,必须通过地址转换将逻辑地址转换成物理地址,这个过程称为地址重定位。
3.进程的内存映像
不同于存放在硬盘上的可执行程序文件,当一个程序调入内存运行时,就构成了选程的内存映像。一个进程的内存映像一般有几个要素:
代码段:即程序的二进制代码,代码段是只读的,可以被多个进程共享。
数据段:即程序运行时加工处理的对象,包括全局变量和静态变量。
进程控制块(PCB):存放在系统区。操作系统通过PCB来控制和管理进程。
堆:用来存放动态分配的变量。通过调用malloc函数动态地向高地址分配空间。
栈:用来实现函数调用。从用户空间的最大地址往低地址方向增长。
4.内存分配与回收
存储管理方式随着操作系统的发展而发展。在操作系统由单道向多道发展时,存储管理方式便由单一连续分配发展为固定分区分配。为了能更好地适应不同大小的程序要求,又从固定分区分配发展到动态分区分配。为了更好地提高内存的利用率,进而从连续分配方式发展到离散分配方式一页式存储管理。引入分段存储管理的目的,主要是满足用户在编程和使用方面的要求,其中某些要求是其他几种存储管理方式难以满足的。