一、Linux内核地址空间

一般来说Linux 内核按照 3:1 的比率来划分虚拟内存(X86等):3 GB 的虚拟内存用于用户空间,1GB 的内存用于内核空间。当然有些体系结构如MIPS使用2:2 的比率来划分虚拟内存:2 GB 的虚拟内存用于用户空间,2 GB 的内存用于内核空间,另外像ARM架构的虚拟空间是可配置(1:3、2:2、3:1)。内核线性地址空间用于为内核的运行提供最基本的支持,也是操作系统赖以存在的基础。所谓内核线性地址空间就是说内核态下虚拟地址与物理地址是线性关系,两者相差一个固定偏差,计算公式为VA(虚拟地址)=PA(物理地址)+PAGE_OFFSET。

二、什么是高端内存

以x86为例linux中内核使用3G-4G的线性地址空间,也就是说总共只有1G的地址空间可以用来映射物理地址空间。但是,如果内存大于1G的情况下内核态线性地址就不够用了。为此内核引入了一个高端内存的概念,把1G的线性地址空间划分为两部分:小于896M物理地址空间的称之为低端内存,这部分内存的物理地址和3G开始的线性地址是一一对应映射的,也就是说内核使用的线性地址空间(VA)3G--(3G+896M)和物理地址空间(PA)0-896M一一对应,PAGE_OFFSET=0xC0000000;剩下的128M的线性空间用来映射剩下的大于896M的物理地址空间,这也就是我们通常说的高端内存区,这部分空间需要MMU通过TLB表来建立动态的映射关系。

三、高端内存映射

高端内存映射有三种方式:

1、  临时映射空间

固定映射空间是内核线性空间中的一组保留虚拟页面空间,位于内核线性地址的末尾即最高地址部分。其地址编译时确定,用于特定用途(如VSYSCALL系统调用,MIPS的cache着色)。由枚举类型  fixed_addresses决定,内核在FIXADDR_START 到 FIXADDR_TOP 之间

在这个空间中,有一部分用于高端内存的临时映射。这块空间具有如下特点: 每个 CPU 占用一块空间;可以用在中断处理函数和可延迟函数的内部,从不阻塞,禁止内核抢占;在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的 km_type 中。

当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。

接口函数:kmap_atomic/kunmap_atomic。 使用从FIX_KMAP_BEGIN到FIX_KMAP_END之间的物理页

2、  长久映射空间

长久映射地址空间是预留的线性地址空间。访问高内存的一种手段。使用方式是先通过alloc_page() 获得了高端内存对应的 page,然后内核从专门为此留出的线性空间分配一个虚拟地址,在 PKMAP_BASE 到 FIXADDR_START 之间。

接口函数:void*kmap(struct *page)、 void kumap(struct *page)

该接口函数在高/低内存都能使用,可以睡眠,数量有限。对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系)。

#definePKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE * (LAST_PKMAP + 1)) & PMD_MASK)

#defineLAST_PKMAP 1024

3、非连续映射地址空间

非连续映射地址空间适用于为不频繁申请释放内存的情况,这样不会频繁的修改内核页表。总的来说,内核主要在以下情况使用非连续映射地址空间:映射设备的I/O空间;为内核模块分配空间;为交换分区分配空间

每个非连续内存区都对应一个类型为vm_struct 的描述符,通过next字段,这些描述符被插入到一个vmlist链表中。

这种方式下高端内存使用简单,因为通过vmalloc() ,在”内核动态映射空间“申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说高端内存有可能映射到”内核动态映射空间“中。

接口函数:vmalloc(vfree):物理内存(调用alloc_page)和线性地址同时申请,物理内存是 __GFP_HIGHMEM类型(分配顺序是HIGH, NORMAL , DMA )(可见vmalloc不仅仅可以映射HIGHMEM页框,它的主要目的是为了将零散的,不连续的页框拼凑成连续的内核逻辑地址空间... );

vmap(vumap):vmalloc的简化版;

ioremap(iounmap):分配I/O映射空间;

下图简单表达了linux内核对虚拟地址的映射,其中highmem区域用于对高端内存映射:

四、MIPS的高端内存

Mips的highmem管理可参见其官方简介:http://www.linux-mips.org/wiki/Highmem

在MIPS32 CPU中不经过MMU转换的内存窗口只有kseg0和kseg1 的512MB的大小,而且这两个内存窗口映射到同一得0~512M的物理地址空间。其余的3G虚拟地址空间需要经过MMU转换成物理地址,这个转换规则是由CPU 厂商实现的。换句话说,在MIPS32 CPU下面访问高于512M的物理地址空间,必须通过MMU地址转换。即按VA=PA+PAGE_OFFSET公式映射的空间最大只有512M,其中PAGE_OFFSET=0x80000000,而在Linux中MIPS32只使用其中的256MB。

MIPS在higmem使用过程中需要注意两个问题:一是要考虑由higmem带来的整个系统性能和稳定性间的平衡,二是highmem不支持cache aliases。

五、总结

高端内存含义为:线性地址空间 PAGE_OFFSET+HIGHSTART至4G的最后线性地址 <==映射==> HIGHSTART以上的物理页框,非直接映射。有3种方法:非连续内存区映射,永久内核映射,临时内核映射(固定映射)。

用户空间当然可以使用高端内存,而且是正常的使用,内核在分配那些不经常使用的内存时,都用高端内存空间(如果有),所谓不经常使用是相对来说的,比如内核的一些数据结构就属于经常使用的,而用户的一些数据就属于不经常使用的。

用户在启动一个应用程序时,是需要内存的,而每个应用程序都有3G的线性地址,给这些地址映射页表时就可以直接使用高端内存。

总之,内核的高端线性地址是为了访问内核固定映射以外的内存资源。实际上高端内存是针对内核一段特殊的线性空间提出的概念,和实际的物理内存是两码事。进程在使用内存时,触发缺页异常,具体将哪些物理页映射给用户进程是内核考虑的事情。在用户空间中没有高端内存这个概念。

注:1、本文中本文中虚拟地址和线性地址没做细致区分,可认为是一个概念。
2、关于highmem的代码分析可参见《关于高端内存的一些笔记》一文:http://bbs.chinaunix.net/thread-1938084-1-1.html

Linux 内存管理之highmem简介的更多相关文章

  1. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  2. Linux内存管理原理【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3695517.html 本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址 ...

  3. Windows内存管理和linux内存管理

    windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或 ...

  4. Linux内核分析(三)----初识linux内存管理子系统

    原文:Linux内核分析(三)----初识linux内存管理子系统 Linux内核分析(三) 昨天我们对内核模块进行了简单的分析,今天为了让我们今后的分析没有太多障碍,我们今天先简单的分析一下linu ...

  5. 伙伴系统之伙伴系统概述--Linux内存管理(十五)

    在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Knowlton设计, ...

  6. 启动期间的内存管理之bootmem_init初始化内存管理–Linux内存管理(十二)

    1. 启动过程中的内存初始化 首先我们来看看start_kernel是如何初始化系统的, start_kerne定义在init/main.c?v=4.7, line 479 其代码很复杂, 我们只截取 ...

  7. 启动期间的内存管理之初始化过程概述----Linux内存管理(九)

    在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检 ...

  8. Linux内存管理 (25)内存sysfs节点解读

    1. General 1.1 /proc/meminfo /proc/meminfo是了解Linux系统内存使用状况主要接口,也是free等命令的数据来源. 下面是cat /proc/meminfo的 ...

  9. Linux内存管理 (1)物理内存初始化

    专题:Linux内存管理专题 关键词:用户内核空间划分.Node/Zone/Page.memblock.PGD/PUD/PMD/PTE.lowmem/highmem.ZONE_DMA/ZONE_NOR ...

随机推荐

  1. bzoj4152[AMPPZ2014]The Captain 最短路

    4152: [AMPPZ2014]The Captain Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1517  Solved: 603[Submi ...

  2. python+eclipse+pydev开发环境搭建

    1.安装配置python2.7(右击我的电脑->属性->高级系统设置->环境变量->系统变量列表中找到Path并双击->变量值中添加";C:\Python27; ...

  3. kafka快速入门

    一.kafka简介 kafka,ActiveMQ,RabbitMQ是当今最流行的分布式消息中间件,其中kafka在性能及吞吐量方面是三者中的佼佼者,不过最近查阅官网时,官方与它的定义为一个分布式流媒体 ...

  4. ds4700更换控制器导致磁盘无法识别-处理方法

    更换DS4700控制器的悲与喜 机型:DS4700     原微码:06.23.xx 更换部件:控制器 (使用的控制器微码07.60.52.00) 误操作过程: 1,关掉存储换控制器 --(兄弟们千万 ...

  5. Linux学习之CentOS(五)--CentOS下VMware-Tools安装

    已经进入到了Linux学习之CentOS的第六篇随笔了,所以这里就介绍一下VMware-Tools的安装. VMware-Tools的安装 VMware-Tools 主要的功能就是让用户在虚拟机和真实 ...

  6. MyBatis 传入参数之parameterType

      在MyBatis的select,insert,update,delete这些元素中都提到了parameterType这个属性.MyBatis现在使用parameterType有基本类型和JAVA复 ...

  7. linux tar解压命令

    linux下使用tar命令 解压语法:tar [主选项+辅选项] 文件或者目录 使用该命令时,主选项是必须要有的,它告诉tar要做什么事情,辅选项是辅助使用的,可以选用.主选项:c 创建新的档案文件. ...

  8. Python中的赋值(复制)、浅拷贝、深拷贝之间的区别

    1.赋值: 只是复制了新对象的引用,不会开辟新的内存空间.  2.浅拷贝: 创建新对象,其内容是原对象的引用.    浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数.    如: ...

  9. geotrellis使用(四十)优雅的处理请求超过最大层级数据

    前言 要说清楚这个题目对我来说可能都不是一件简单的事情,我简单尝试. 研究 GIS 的人应该都清楚在 GIS 中最常用的技术是瓦片技术,无论是传统的栅格瓦片还是比较新颖的矢量瓦片,一旦将数据切好瓦片就 ...

  10. AutoMagic-开源自动化平台构建思路

    最近在github上看到AutoMagic自动化平台开源了,一时手痒,就试着搭了一套环境,现在把思路和大家说一说. AutoMagic从其工作分工分两部分: 1:Web端管理平台 管理平台基于Pyth ...