没有合适的资源?快使用搜索试试~ 我知道了~
第六章 Li nux 内存管理存储器是一种必须仔细管理的重要资源。在理想的情况下,每个程序员都喜欢无穷大、快速并且内容不易变(即掉电后内容不会丢失)的存储器,同
资源详情
资源评论
资源推荐
– 147 –
第六章 Linux 内存管理
存储器是一种必须仔细管理的重要资源。在理想的情况下,每个程序员都喜欢无穷大、
快速并且内容不易变(即掉电后内容不会丢失)的存储器,同时又希望它是廉价的。但不幸
的是,当前技术没有能够提供这样的存储器,因此大部分的计算机都有一个存储器层次结构,
即少量、快速、昂贵、易变的高速缓存(cache);若干兆字节的中等速度、中等价格、易变
的主存储器(RAM);数百兆或数千兆的低速、廉价、不易变的磁盘。如图 6.1 所示,这些资
源的合理使用与否 ,直接关系着系统的效率。
图 6.1 存储器的层次结构
Linux 内存管理是内核最复杂的任务之一。主要是因为它用到许多 CPU 提供的功能,而
且和这些功能密切相关。正因为如此,我们在第二章较详细地介绍了 Intel 386 的段机制和
页机制,可以说这是进行内存管理分析的物质基础 。这一章用大量的篇幅描述了 Linux 内存
管理所涉及到的各种机制,如内存的初始化机制、地址映射机制、请页机制、交换机制、内
存分配和回收机制、缓存和刷新机制以及内存共享机制,最后还分析了程序的创建和执行。
6.1 Linux 的内存管理概述
Linux 是为多用户多任务设计的操作系统,所以存储资源要被多个进程有效共享;且由
深入分析
Linux
内核源代码
– 148 –
于程序规模的不断膨胀,要求的内存空间比从前大得多。 Linux 内存管理的设计充分利用了
计算机系统所提供的虚拟存储技术,真正实现了虚拟存储器管理。
第二章介绍的 Intel 386 的段机制和页机制是 Linux 实现虚拟存储管理的一种硬件平
台。实际上, Linux 2.0 以上的版本不仅仅可以运行在 Intel 系列个人计算机上,还可以运
行在 Apple 系列、DEC Alpha 系列、MIPS 和 Motorola 68k 等系列上, 这些平台都支持虚拟
存储器管理,我们之所以选择 Intel 386,是因为它具有代表性和普遍性。
Linux 的内存管理主要体现在对虚拟内存的管理。我们可以把 Linux 虚拟内存管理功能
概括为以下几点:
• 大地址空间;
• 进程保护;
• 内存映射;
• 公平的物理内存分配;
• 共享虚拟内存。
关于这些功能的实现,我们将会陆续介绍。
6.1.1 Linux 虚拟内存的实现结构
我们先从整体结构上了解 Linux 对虚拟内存的实现结构,如图 6.2 所示。
page_ip swap_state
swapfile swap
kswapd
swa
p
page_alloc
memory
mmap
mremap filemap
mma
p
结构特定的模块
系统调用接口
CMMU
core
模块
源程序文件
守护进程
依赖
图示符号
图 6.2 Linux 虚拟内存的实现结构
从图 6.2 中可看到实现虚拟内存的组成模块。其实现的源代码大部分放在/mm 目录下。
第六章
Linux
内存管理
– 149 –
(1)内存映射模块(mmap):负责把磁盘文件的逻辑地址映射到虚拟地址,以及把虚拟地
址映射到物理地址。
(2)交换模块(swap):负责控制内存内容的换入和换出,它通过交换机制,使得在物
理内存的页面(RAM 页)中保留有效的页 ,即从主存中淘汰最近没被访问的页,保存近来访
问过的页。
(3)核心内存管理模块(core):负责核心内存管理功能,即对页的分配、回收、释放
及请页处理等,这些功能将被别的内核子系统(如文件系统)使用。
(4)结构特定的模块:负责给各种硬件平台提供通用接口,这个模块通过执行命令来改
变硬件 MMU 的虚拟地址映射,并在发生页错误时,提供了公用的方法来通知别的内核子系统。
这个模块是实现虚拟内存的物理基础。
6.1.2 内核空间和用户空间
从第二章我们知道,Linux 简化了分段机制,使得虚拟地址与线性地址总是一致,因此,
Linux 的虚拟地址空间也为 0~4G 字节。Linux 内核将这 4G 字节的空间分为两部分。将最高
的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF),供内核使用,称为“内核空间”。而将
较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF),供各个进程使用,称为“用户空
间”。因为每个进程可以通过系统调用进入内核,因此,Linux 内核由系统内的所有进程共享。
于是,从具体进程的角度来看,每个进程可以拥有 4G 字节的虚拟空间。图 6.3 给出了进程
虚拟空间示意图。
虚拟内核空间(1GB)
进程
1
的
用户空间
(3GB)
进程
2
的
用户空间
(3GB)
…
进程
n
的
用户空间
(3GB)
图 6.3 Linux 进程的虚拟空间
Linux 使用两级保护机制:0 级供内核使用,3 级供用户程序使用。从图 6.3 中可以看出,
每个进程有各自的私有用户空间(0~3G),这个空间对系统中的其他进程是不可见的。最高
的 1G 字节虚拟内核空间则为所有进程以及内核所共享。
1.虚拟内核空间到物理空间的映射
内核空间中存放的是内核代码和数据,而进程的用户空间中存放的是用户程序的代码和
数据。不管是内核空间还是用户空间,它们都处于虚拟空间中。读者会问,系统启动时,内
核的代码和数据不是被装入到物理内存吗?它们为什么也处于虚拟内存中呢?这和编译程序
有关,后面我们通过具体讨论就会明白这一点。
虽然内核空间占据了每个虚拟空间中的最高 1G 字节,但映射到物理内存却总是从最低
深入分析
Linux
内核源代码
– 150 –
地址(0x00000000)开始。如图 6.4 所示,对内核空间来说,其地址映射是很简单的线性映
射,0xC0000000就是物理地址与线性地址之间的位移量,在Linux代码中就叫做PAGE_OFFSET。
0
3G
4G
0
X
虚地址空间 物理地址空间
图 6.4 内核的虚拟地址空间到物理地址空间的映射
我们来看一下在 include/asm/i386/page.h 中对内核空间中地址映射的说明及定义:
/*
* This handles the memory map.. We could make this a config
* option, but too many people screw it up, and too few need
* it.
*
* A __PAGE_OFFSET of 0xC0000000 means that the kernel has
* a virtual address space of one gigabyte, which limits the
* amount of physical memory you can use to about 950MB.
*
* If you want more physical memory than this then see the CONFIG_HIGHMEM4G
* and CONFIG_HIGHMEM64G options in the kernel configuration.
*/
#define __PAGE_OFFSET (0xC0000000)
……
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
源代码的注释中说明,如果你的物理内存大于 950MB,那么在编译内核时就需要加
CONFIG_HIGHMEM4G 和 CONFIG_HIGHMEM64G 选项,这种情况我们暂不考虑。如果物理内存小于
950MB,则对于内核空间而言,给定一个虚地址 x,其物理地址为“x- PAGE_OFFSET”,给定
一个物理地址 x,其虚地址为“x+ PAGE_OFFSET”。
这里再次说明,宏__pa()仅仅把一个内核空间的虚地址映射到物理地址,而决不适用于
用户空间,用户空间的地址映射要复杂得多。
第六章
Linux
内存管理
– 151 –
2.内核映像
在下面的描述中,我们把内核的代码和数据就叫内核映像(Kernel Image)。当系统启
动时,Linux 内核映像被安装在物理地址 0x00100000 开始的地方,即 1MB 开始的区间(第 1M
留作它用)。然而,在正常运行时, 整个内核映像应该在虚拟内核空间中,因此,连接程序
在连接内核映像时,在所有的符号地址上加一个偏移量 PAGE_OFFSET,这样,内核映像在内
核空间的起始地址就为 0xC0100000。
例如,进程的页目录 PGD(属于内核数据结构)就处于内核空间中。在进程切换时,要
将寄存器 CR3 设置成指向新进程的页目录 PGD,而该目录的起始地址在内核空间中是虚地址,
但 CR3 所需要的是物理地址,这时候就要用__pa()进行地址转换。在 mm_context.h 中就有这
么一行语句:
asm volatile(“movl %0,%%cr3”: :”r” (__pa(next->pgd));
这是一行嵌入式汇编代码,其含义是将下一个进程的页目录起始地址 next_pgd,通过
__pa()转换成物理地址,存放在某个寄存器中,然后用 mov 指令将其写入 CR3 寄存器中。经
过这行语句的处理,CR3 就指向新进程 next 的页目录表 PGD 了。
6.1.3 虚拟内存实现机制间的关系
Linux 虚拟内存的实现需要各种机制的支持,因此,本章我们将对内存的初始化进行描
述以后,围绕以下几种实现机制进行介绍:
• 内存分配和回收机制;
• 地址映射机制;
• 缓存和刷新机制;
• 请页机制;
• 交换机制;
• 内存共享机制。
这几种机制的关系如图 6.5 所示。
图 6.5 虚拟内存实现机制间的关系
剩余118页未读,继续阅读
申增浩
- 粉丝: 20
- 资源: 297
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0