操作系统闲谈05——内存管理
一、 内存管理的基本方式
01 段式内存管理
将程序按照逻辑关系划分为段,每个段的大小不等,比如从下到上(代码段、数据段、bss段、栈、文件映射、堆等等),然后通过地址映射机制转换为实际的物理地址。
可以根据GDT,全局段描述符表找到段号和段基址(逻辑地址)的对应关系,然后通过段基址+段内偏移就可以得到物理地址
缺点:会产生外部碎片,进程必须全部装入内存
02 页式内存管理
将各进程的虚拟空间划分为若干长度相等的页,然后按页的大小建立页表,可以通过页表映射找到对应的内存块。
优点:没有外碎片,每个内碎片不超过页的大小。
缺点:程序全部装入内存,要求有相应的硬件支持(硬件产生缺页中断)。
解决内部碎片和外部碎片 slab和buddy系统
操作系统闲谈04——内存管理方式
03 段页式内存管理
内存以段位基本单位,,每个段又划分为若干个页。需要段表和页表共同管理内存的分配与释放。
二、 内存的分配与释放
01 物理地址内存的分配与释放
主要采用链表结构
使用了一个名叫page的结构体管理物理内存,结构体中包括了页的大小、页的状态以及指向相邻页的指针。
Linux内核使用这些指针来构建了一个逻辑链表,当需要分配内存的时候,会从链表中查找第一个空闲页并把它标记为已使用。
释放内存的时候,会把相应的页标记为空闲,并把它插入到链表对应的位置
02 虚拟用户进程空间内存的分配与释放
C++语言层次
-
智能指针 栈上的对象出作用域自动析构 自动管理内存的分配与释放
-
new delete
C语言层次
- malloc free
系统调用
-
sbrk brk
-
mmap
malloc 是如何分配内存的
内核空间
kmalloc
vmalloc
操作系统闲谈04——内存管理方式
三、 虚拟地址与物理地址的转换
01 软件实现——页表
时间上改进 TLB快表
在系统每次访问虚存页时,都要在内存的所有页表中寻找该页的页框,这是一个很费时间的工作。但是,人们发现,系统一旦访问了某一个页,那么系统就会在一段时间内稳定地工作在这个页上。所以,为了提高访问页表的速度,系统还配备了一组正好能容纳一个页表的硬件寄存器,这样当系统再访问虚存时,就首先到这组硬件寄存器中去访问,系统速度就快多了。这组存放当前页表的寄存器叫做快表。
空间上改进 多级页表
为了通用,Linux系统使用了三级页表结构:页目录、中间页目录和页表。PGD为顶级页表,是一个pgd_t数据类型(定义在文件linux/include/page.h中)的数组,每个数组元素指向一个中间页目录;PMD为二级页表,是一个pmd_t数据结构的数组,每个数组元素指向一个页表;PTE则是页表,是一个pte_t数据类型的数组,每个元素中含有物理地址。
02 硬件实现——MMU内存管理单元
在Linux系统中,页表是用于实现内存管理单元 (MMU) 的一种数据结构。MMU是处理器的一个硬件单元,它负责将虚拟内存地址转换为物理内存地址。页表是用于定位物理内存地址的数据结构,它储存了虚拟内存地址到物理内存地址的映射关系。
当程序请求访问内存时,MMU使用页表来确定请求的内存地址的物理内存位置。如果请求的内存地址不在物理内存中,MMU会触发一个缺页异常,此时内存管理子系统就会调入该页的数据。
因此,可以说页表是实现虚拟内存的关键数据结构,而MMU则是其实现的核心硬件单元。在Linux系统中,内存管理子系统通过维护页表来管理虚拟内存,并通过与MMU的协作来实现对虚拟内存的访问控制。