Linux内存布局
在上一篇博文里,我们已经看到Linux如何有效地利用80x86的分段和分页硬件单元把逻辑地址转换为线性地址,在由线性地址转换到物理地址。那么我们的应用程序如何使用这些逻辑地址,整个内存的地址布局又是怎样的?打一个比方,内存就像一座城市,而居住在这个城市里的市民就像是各个进程,一个市民吃喝拉撒睡,当然就得用于“房子”、“车子”、“票子”等各种各样的资源。有些资源是固定的,如“房子”,我们称之为静态数据;有些资源是动态的,如“车子”,我们称之为动态数据;有些资源是用来购买(产生)数据的,如“票子”,我们称之为代码。
现在,我们就来看看内存这座巨大的城市史如何布局的。在系统初始化阶段,内核首先在实模式下建立一个物理地址映射来指定哪些物理地址范围对内核可用而哪些不可用(主要是根据映射硬件设备I/O的共享内存,或者根据相应的页框含有的BIOS数据)。
内存的某些部分将永久地分配给BOIS或内核,用来存放BIOS信息、内核代码以及静态内核数据结构。所以内核将下列页框记为保留:
• 在不可用的物理地址范围内的页框,一般用来存放BIOS信息。
• 含有内核代码和已初始化的数据结构的页框。
标记为保留页框中的页,绝不能被动态分配或交换到磁盘上。
一般来说,Linux内核安装在RAM中从物理地址0x00100000开始的地方,也就是说,从第二个MB开始。所需页框总数依赖于内核的配置方案:典型的配置所得到的内核可以完全被安装在小于3MB的RAM中。
为什么内核没有安装在RAM第一个MB开始的地方?主要是为具体的PC体系结构所考虑。例如:
• 页框0由BIOS使用,存放加电自检(Power-On Self-Test,POST)期间检查到的硬件配置。因此,很多膝上型电脑的BIOS甚至在系统初始化后还将数据写到该页框。
• 物理地址从0x000a0000 到 0x000fffff的范围通常留给BIOS例程,并且映射ISA图形卡上的内部存储器。这个区域就是所有IBM兼容PC上从640KB到1MB之间著名的洞:物理地址存在但被保留,对应的页框不能由操作系统使用。
• 前1MB内的其他页框可能由特定计算机模型保留。例如,IBM 笔记本电脑把0x0a页框映射到0x9f页框。
在启动过程的早期阶段,内核询问BIOS并了解物理内存的大小,并调用machine_specific_memory_setup()函数建立物理地址映射。假设我们的内存是128MB,那么,第一个MB就给BIOS了。整个128MB的内存被物理映射成以下布局:
0x00000000 - 0x0009ffff 除第一个页框外的640K空间可用
0x000a0000 - 0x000effff 保留
0x000f0000 - 0x000fffff 保留给BIOS例程
0x00100000 - 0x07feffff 126.9MB可用空间
0x07ff0000 - 0x07ff2fff ACPI data
0x07ff3000 - 0x07ffffff ACPI NVS
0xffff0000 - 0xffffffff 保留
这里简单介绍一下128MB内存的末尾,从0x07ff0000 到0x07ff2fff的物理地址范围中存有加电自测(POST)阶段由BIOS写入的系统硬件设备信息;在初始化阶段,内核把这些信息拷贝到一个合适的内核数据结构中,然后认为这些页框是可用的。相反,从0x07ff3000到0x07ffffff的物理地址范围被映射到硬件设备的ROM芯片。从0xffff0000开始的物理地址范围标记为保留,因为它由硬件映射到了BIOS的ROM芯片。注意BIOS也许并不提供一些物理地址范围的信息(在上述图中,范围是0x000a0000到 0x000effff)。为安全可靠起见,Linux假定这样的范围是不可用的。
虽然,我们看到第一个MB里,BIOS并没有用完,但是为了避免把内核装入一组不连续的页框里,影响性能,Linux便跳过第1MB的RAM,之间从第2个MB开始加载。其实一般来说,对于两个MB,也就是512个页框,对初始化时的内核代码及一些静态数据,已经足够了。
内核可能不会见到BIOS报告的所有物理内存:例如,如果未使用PAE支持来编译,即使有更大的物理内存可供使用,内核也只能寻址4GB大小的RAM。setup_memory()函数在machine_specific_memory_setup()执行后被调用:它分析物理内存区域表并初始化一些变量来描述内核的物理内存布局,这些变量如下表所示:
变量名称 |
说明 |
num_physpages |
最高可用页框的页框号 |
totalram_pages |
可用页框的总数量 |
min_low_pfn |
RAM 中在内核映像后第一个可用页框的页框号 |
max_pfn |
最后一个可用页框的页框号 |
max_low_pfn |
被内核直接映射的最后一个页框的页框号(低地址内存) |
totalhigh_pages |
内核非直接映射的页框的总数(高地址内存) |
highstart_pfn |
内核非直接映射的第一个页框的页框号 |
highend_pfn |
内核非直接映射的最后一个页框的页框号 |
下图显示Linux怎样填充前3MB的RAM。
我们看到图中可用的页框,是内存的其余部分,我们称为动态内存,这不仅是进程所需的宝贵资源,也是内核本身所需的宝贵资源。实际上,整个系统的性能取决于如何有效地管理动态内存。因此,现在所有多任务操作系统都在尽力优化对动态内存的使用,也就是尽可能做到当需要是分配,不需要时释放。
后面的博文中,我们将重点讨论内核如何给自己分配动态内存。主要包括页框管理、高端内存映射、伙伴系统算法、slab分配器、内存池、非连续内存区管理。
Linux内存布局的更多相关文章
- Linux 内存布局
本文主要简介在X86体系结构下和在ARM体系结构下,Linux内存布局的概况,力求简单明了,不过多深入概念,多以图示的方式来记忆理解,一图胜万言. Technorati 标签: 内存 布局 ...
- linux 内存布局以及tlb更新的一些理解
问题: 1.内核线程是否有vma线性区? 2.单线程的一个进程,它修改了自己的页表,是否需要发送ipi来通知其他核更新tlb? 3.普通进程,在32位和64位,对应的线性区的最大地址能到多少? 在64 ...
- linux内存布局------深入理解计算机系统
- linux系统进程的内存布局
内存管理模块是操作系统的心脏:它对应用程序和系统管理非常重要.今后的几篇文章中,我将着眼于实际的内存问题,但也不避讳其中的技术内幕.由于不少概念是通用的,所以文中大部分例子取自32位x86平台的Lin ...
- linux内存管理解析1----linux物理,线性内存布局及页表的初始化
主要议题: 1分页,分段模式及实模式 2Linux分页 3linux内存线性地址空间布局及物理内存空间布局 4linux页表初始化及代码解析 1.1.1内存寻址和保护模式 在X86平台上,内存控制单元 ...
- [内存管理]linux X86_64处理器的内存布局图
linux X86 64位内存布局图
- Linux内存管理 (3)内核内存的布局图
专题:Linux内存管理专题 关键词:内核内存布局图.lowmem线性映射区.kernel image.ZONE_NORMAL.ZONE_HIGHMEM.swapper_pg_dir.fixmap.v ...
- Linux内存初始化(三) 内存布局
一.前言 同样的,本文是内存初始化文章的一份补充文档,希望能够通过这样的一份文档,细致的展示在初始化阶段,Linux 4.4.6内核如何从device tree中提取信息,完成内存布局的任务.具体的c ...
- Linux进程地址空间 && 进程内存布局[转]
一 进程空间分布概述 对于一个进程,其空间分布如下图所示: 程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码. 初始化过的数据(Data):在程序运行初已经对变量进行初始 ...
随机推荐
- 转: OGG Checkpoint 详解
1. OGG Checkpoint 详解 定位中断的位置,下次启动从中断的位置开始恢复. 1.target 端配置: 2.一条记录对应一个replicat 一. Extract Checkpoints ...
- 生成makefile文件编译源文件
1.利用CodeBlock的cbp文件生成makefile文件 reverse@ubuntu:~/Desktop/CreateMakeFile$ ls cbp2make.linux-x86 freeg ...
- Andorid APK反逆向解决方案---梆梆加固原理探寻
本文章由Jack_Jia编写,转载请注明出处. 文章链接:http://blog.csdn.net/jiazhijun/article/details/8892635 作者:Jack_Jia ...
- Naive Bayes在mapreduce上的实现(转)
Naive Bayes在mapreduce上的实现 原文地址 http://www.cnblogs.com/sunrye/p/4553732.html Naive Bayes是比较常用的分类器,因为思 ...
- PAT (Advanced Level) 1069. The Black Hole of Numbers (20)
简单题. #include<cstdio> #include<cstring> #include<cmath> #include<vector> #in ...
- 一个int类型引发的bug
一.引言 今天我在项目开发中,遭遇了一个莫名其妙的问题,概括加抽象后形成如下问题:在使用MyBatis的XML语句实现Dao层接口 List<Person> selectBySome(@P ...
- Linux:crontab的安装以及使用方法
安装crontab: [root@wulaoer ~]# yum install vixie-cron [root@wulaoer ~]# yum install crontabs 说明:vixie- ...
- JAVA基础--接口 interface
接口是抽象方法和常量值定义的集合, 接口是一种特殊的抽象类, 只包含常量和方法的定义, 而没有变量和方法的实现. 接口->接口: extends, 类->类: extends, 类-> ...
- CodeForces 610C Harmony Analysis
构造 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> us ...
- Ketama Consisent Hash
问题描述 有一些目标节点 v1, v2...vn 需要一个算法,能够将任意key映射到目标节点中的一个vx 评价方式 1. 对于一个比较大的key集合,分布在各个目标节点的key的数量要尽可能均匀 2 ...