当前课程知识点:Linux 内核分析与应用 > 第4章 内存管理 > 4.3 物理内存分配与回收机制(上) > Video
大家好 这一讲呢我们给大家介绍一下
内存的分配与回收机制
当我们说一个进程在执行的时候呢我们在说什么
从操作系统的角度看呢
一个进程最关键的特征呢
是它拥有独立的虚拟地址空间
创建并执行一个进程呢
通常需要执行如下步骤
首先要建立可执行文件与虚拟地址空间的映射
当执行一个程序的时候加载器呢
读取的是可执行文件的头部
建立虚拟空间跟可执行文件的映射
这个主要是调用do_mmap()函数
同时虚拟地址空间所需的数据结构mm_struct结构
和vm_area_struct结构呢
也填充相应的值
如图左边的虚拟内存部分
第二步就是将指令寄存器呢
设置为可执行文件的入口
并启动运行
当我们在说一个程序在装载的时候在说什么呢
在上述步骤之后呢执行文件的指令和数据加载进内存
但是并没有真正地装入到物理内存
只是通过可执行文件的头部信息呢
建立起可执行文件
与虚拟地址空间的映射关系而已
而真正的加载过程将在发生缺页异常处理的时候进行
装载的过程有以下的步骤
首先内核根据上面建立的映射关系
找到所需的内容在可执行文件的位置
然后分配一个物理内存页面
并将可执行文件内容装载到该内存页中
最后建立该物理页面和虚拟地址空间的映射关系
也就是说填充页表
最后把控制权交给该进程如图右边所示
这其中涉及的异常处理机制我们前面已经给大家介绍过了
那么当我们调用malloc的时候内核到底做了什么
我们还要看一下当我们在用户程序申请内存时调用malloc时候呢
内核做了什么实际上呢
它负责为进程动态的申请一段内存
操作系统从堆中分配一块内存
并把首地址返回给用户
malloc申请内存的大小不一样 最终调用的系统调用也不一样如图所示
那么内核是不是立即为进程分配了物理内存呢 答案是否定的
依然是要通过请页机制
下面我们就来看一下物理内存的管理
我们说请页机制可以为进程请求物理内存
那么物理内存在内核中究竟是如何管理如何分配的呢
接下来我们将从物理内存的逻辑模型说起
首先我们看一下内核空间的划分
在X86的32体系架构上呢
内核空间的地址范围是3G到4G之间
内核空间的第一部分试图将系统的
所有物理内存线性地映射到虚拟地址空间中
但是最多只能映射HIGH MEMORY(默认值为896M)
大小的物理内存
当大于HIGH MEMORY的时候呢
物理内存将映射到内核空间的后部分
按照这样的映射原则呢
那么从0到HIGH MEMORY的
物理内存我们把它称为低端内存
大于HIGH MEMORY的物理内存我们称之为高端内存
从这个图我们可以看出内核采用了
三种机制将高端内存映射到了内核空间
一种叫永久的内核映射
一种呢叫固定映射
那么第三种呢叫vmalloc机制
下面我们来介绍一下内核虚拟地址如何转化成物理地址
内核为线性映射的内存区呢
提供了物理地址和虚拟地址之间的转换函数
一个是呢就是__pa函数 它返回虚拟地址
对应的物理地址
那么__va返回物理地址
对应的虚拟地址
内核地址空间是从page_offset开始的 因此呢
上述两个地址转化函数的源代码实现如下
从这两个宏定义我们可以看出 这完全是一种线性关系
那么物理内存管理有什么样的机制呢
即物理内存在内核空间的映射原理呢
物理内存的管理方式也有所不同
内核中 物理内存的管理采取
以下四种机制
第一种是伙伴算法
伙伴算法负责大块连续物理内存的分配和释放
它是以页框为基本单位的 该机制可以避免外碎片的发生
那么第二种机制叫每CPU页框高速缓存
内核经常请求和释放单个页框
该缓存可以包含预先分配的页框
用于满足本地CPU发出的单一页框请求
第三种机制叫slab缓存
它呢是负责小块物理内存的分配
并且它也作为高速缓存
主要针对内核中经常分配并释放的对象
第四种机制是vmalloc机制
vmalloc机制使得内核通过连续的线性
址来访问非连续的物理页框
这样可以最大限度的使用高端物理内存
下来我们来介绍一下分配小内存的slab分配机制
我们说伙伴算法呢它是
负责大块连续物理内存的分配和释放
它是以页框为基本单位的
那么这个呢我们在下一讲进行详细的介绍
那么分配小块的内存怎么办呢
slab分配方式就是为此而提出的
slab分配最初是为了
解决物理内存的内部碎片而提出的
它将内核中常用的数据结构看作对象
slab分配器为每一种对象建立高速缓存
内核对该对象的分配和释放呢
均是在这块高速缓存中操作 如图所示
我们可以看到每种对象的高速缓存呢
存实际上是由若干个slab组成
而每个slab是由若干个页框组成的
虽然slab分配器可以分配比单个页框
更小的内存块 但是呢
它所需要的所有的内存实际上还是通过
伙伴算法来分配的
slab分配机制分为两种
一种叫通用缓存 一种叫专用缓存
通用缓存是什么意思呢它是针对一般情况的
一般适合于分配
任意大小的物理内存
提供的内核接口函数叫什么呢 叫kmalloc()
那么专用缓存是干什么的呢 它是对特定的对象的
比如要为进程控制块呢
创建一个高速缓存那么就可以
调用它的专用缓存
下面我们介绍一下内核空间非连续内存区的分配
非连续内存区位于什么地方呢
它位于3G到4G之间的
内核空间的高端内存区 如图所示
我们知道物理上连续的映射对于内核是最好的
但不是总能成功
在分配一大块内存的时候呢
可能无法找到连续的内存块
所以内核使用vmalloc接口函数
来分配在虚拟内存中连续
但是在物理内存中不一定连续的内存
使用vmalloc最好的实例就是为内核模块分配内存
因为模块可能在任何时候加载那么
如果模块数据较多的时候呢 无法保证足够的连续内存可用
所以这个时候就要使用vmalloc
那么vmalloc和kmalloc之间有什么样的区别呢
这两个函数都用于内核空间的内存分配
kmalloc分配的内存是位于3G到HIGH MEMORY之间
这段内核空间与物理内存的映射是一一对应的
而vmalloc分配的内存在VMALLOC_START到VMALLOC_END之间
这段非连续内存区映射到物理内存也可能是非连续的
所以vmalloc分配的物理地址呢无需连续
而kmalloc确保页在物理上是连续的
这是它们二者之间的主要区别
下面我们总结一下
当我们申请内存时内核到底做了什么
这张图我们可以看出
我们从用户进程发出内存分配请求的时候呢
到内核最终分配物理内存
这中间内核要做大量的工作
那么这一讲呢概要地介绍了vmalloc和kmalloc
但它们最终都要调用伙伴算法
通过get_free_page()内核函数将获得物理内存
那么下一讲将对伙伴算法进行介绍
参考资料我们阅读《深入理解LINUX内核》第三版的
第八章
最后大家带着思考离开
第一个问题内核空间是否有高端内存的概念
第二个问题64位内核中呢
有高端内存的说法吗?
第三个问题在32位和64位系统上
用户进程能访问多少物理内存
内核代码能访问多少物理内存
那么这一讲我们就讲到这里
谢谢大家
-1.1 Linux操作系统概述
-1.2 Linux内核结构以及内核模块编程
--Video
-1.3 Linux内核源码中的双链表结构
--Video
-1.4 源码分析-内核中的哈希表
--Video
-1.5 动手实践-Linux内核模块的插入和删除
--Video
-第1章 概述--章节测验
-2.1 内存管理之内存寻址
--Video
-2.2 段机制
--Video
-2.3分页机制
--Video
-2.4 动手实践-把虚拟地址转换成物理地址
--Video
-第2章 内存寻址--章节测验
-3.1 进程概述
--Video
-3.2 Linux进程创建
--Video
-3.3 Linux进程调度
--Video
-3.4 动手实践-打印进程描述符task_struct中的字段
--Video
-3.5工程实践-基于内核模块的负载监控
--Video
-第3章 进程管理--章节测验
-4.1 Linux内存管理机制
--Video
-4.2 进程用户空间管理机制
--Video
-4.3 物理内存分配与回收机制(上)
--Video
-4.4 物理内存分配与回收机制(下)
--Video
-4.5 动手实践-Linux内存映射基础(上)
--Video
-4.6 动手实践-Linux内存映射实现(中)
--Video
-4.7 动手实践-Linux内存映射测试(下)
--Video
-4.8 初学者对内存管理的常见疑惑
-第4章 内存管理--章节测验
-5.1 中断机制概述
--Video
-5.2 中断处理机制
--Video
-5.3 中断下半部处理机制
--Video
-5.4 时钟中断机制
--Video
-5.5 动手实践-中断上半部的代码分析及应用
--Video
-5.6 动手实践-中断下半部的代码分析及应用
--Video
-第5章 中断--章节测验
-6.1 Linux中的各种API
--Video
-6.2 系统调用机制
--Video
-6.3 动手实践-添加系统调用(系统调用日志收集系统)
--Video
-第6章 系统调用--章节测验
-7.1 内核同步概述
--Video
-7.2 内核同步机制
--Video
-7.3 动手实践-内核多任务并发实例(上)
--Video
-7.4 动手实践-内核多任务并发实例(下)
--Video
-第7章 内核同步--章节测验
-8.1 虚拟文件系统的引入
--Video
-8.2 虚拟文件系统的主要数据结构
--Video
-8.3 文件系统中的各种缓存
--Video
-8.4 页高速缓存机制以及读写
--Video
-8.5 动手实践-编写一个文件系统(上)
--Video
-8.6 动手实践-编写一个文件系统(中)
--Video
-8.7 动手实践-编写一个文件系统(下)
--Video
-第8章 文件系统--章节测验
-9.1 设备驱动概述
--Video
-9.2 I/O空间管理
--Video
-9.3 设备驱动模型
--Video
-9.4 字符设备驱动程序简介
--Video
-9.5 块设备驱动程序简介
--Video
-9.6 动手实践-编写字符设备驱动程序
--Video
-9.7工程实践-编写块设备驱动的基础(上)
--Video
-9.8 工程实践-块设备驱动程序分析(中)
--Video
-9.9 工程实践-块设备驱动程序实现(下)
--Video
-第9章 设备驱动--章节测验
-致谢与说明
--Video