在free命令中有个参数l,它表示 show detailed low and high memory statistics。其实最先是对High Memory总是为零有些不解(Linux是64为)。其实更不解的是关于low memory、high memory。那么关于low memory和high memory是怎么一回事呢?如下截图所示:

一直对这个概念不解,直到看到关于linux kernel里的high memory 这篇文章。下面文字全部摘自这篇文章

今天有人问我linux kernel里的high memory是怎么回事,说的比较乱,现在整理下。

high memory只存在于32位kernel下,以下文字都针对32位kernel。

1)什么是high memory,为什么要有high memory

Linux人为的把4G虚拟地址空间(32位地址最多寻址4G)分为3G+1G,其中0~3G为用户程序地址空间,3G~4G为kernel地址空间(为什么要这么分?为什么用户程序和kernel不能各自独享4G虚拟地址空间?这两个问题下次再说吧,这里不表),这就是说kernel最多寻址1G的虚拟地址空间。

当CPU启用MMU的paging机制后,CPU访问的是虚拟地址,然后由MMU根据页表转换成物理地址。页表是由kernel维护的,所以kernel可以决定1G的虚拟地址空间具体映射到什么物理地址。但是kernel最多只有3G~4G这1G地址空间,所以不管kernel怎么映射,最多只能映射1G的物理内存。所以如果一个系统有超过1G的物理内存,在某一时刻,必然有一部分kernel是无法直接访问到的(这个一定要想清楚,不然无法明白high memory)。另外,kernel除了访问内存外,还需要访问很多IO设备。在现在的计算机体系结构下,这些IO设备的资源(比如寄存器,片上内存等)一般都是通过MMIO的方式映射到物理内存地址空间来访问的,就是说kernel的1G地址空间除了映射内存,还要考虑到映射这些IO资源--换句话说,kernel还需要预留出一部分虚拟地址空间用来映射这些IO设备(ioremap就是干这个的)。

Linux kernel采用了最简单的映射方式来映射物理内存,即把物理地址+3G按照线性关系直接映射到kernel空间。考虑到一部分kernel虚拟地址空间需要留给IO设备(以及一些其他特殊用途),Linux kernel最多直接映射896M物理内存,而预留了最高端的128M虚拟地址空间给IO设备(还有其他的用途)。所以,当系统有大于896M内存时,超过896M的内存kernel就无法直接访问到了(想明白了么?),这部分内存就是high memory。那kernel就永远无法访问到超过896M的内存了马?不是的,kernel已经预留了128M虚拟地址,我们可以用这个地址来动态的映射到high memory,从而来访问high memory。所以预留的128M除了映射IO设备外,还有一个重要的功能是提供了一种动态访问high memory的一种手段(kmap主要就是干这个的,当然还有vmalloc)。

当然,在系统物理内存<896M,比如只有512M的时候,就没有high memory了,因为512M的物理内存都已经被kernel直接映射。事实上,在物理内存<896M时,从3G+max_phy ~ 4G的空间都作为上述的预留的内核地址空间(未考证)。

要理解high memory,关键是把物理内存管理,虚拟地址空间管理,以及两者间的映射(页表管理)三个部分分开考虑,不要把物理内存管理和虚拟地址空间管理混在一起。比如high memory也参与kernel的物理内存分配,你调用get_page得到的物理页有可能是low memory,也可以是high memory,这个物理页可以被映射到kernel,同时也可以被映射到user space。再比如vmalloc,只保证返回的虚拟地址是在预留的vmalloc area里,对应的物理内存,可以是low memory,也可以是high memory。当然出于性能考虑,kernel可能会优先分配直接映射的low memory,但我们不能假设high memory就不会被分配到。

一些结论:

1)high memory针对的是物理内存,不是虚拟内存,更确切的,虚拟地址空间。

2)high memory也是被内核管理的(有对应的page结构),只是没有映射到内核虚拟地址空间。当kernel需要分配high memory时,通过kmap等从预留的地址空间中动态分配一个地址,然后映射到high memory,从而访问这个物理页。

3)high memory和low memory一样,都是参与内核的物理内存分配,都可以被映射到kernel地址空间,也都可以被映射到user space地址空间。

4)物理内存<896M时,没有high memory,因为所有的内存都被kernel直接映射了。

5)64位系统下不会有high memory,因为64位虚拟地址空间非常大(分给kernel的也很大),完全能够直接映射全部物理内存。

2)题外话1 -- 关于最高端的128M内核虚拟地址(或者当物理内存<896M时更大)的分配:

这部分地址空间被划分为4段,分别是fixed mapping,kmap area,vmalloc area,还有8M用来catch kernel指针错误。其中fixed mapping主要用在boot阶段用来永久性映射一些物理地址固定的数据结构或者硬件地址(比如ACPI表,APIC地址,等等)。kmap area是kernel用来临时建立映射来访问物理页用的,可用的地址空间也比较小。128M中绝大部分reserve了给vmalloc area,vmalloc和ioremap返回的都是这个空间里的地址。

另外,在《Understanding the Linux Virtual Memory Manager》这本书中有linux 进程地址空间划分的详细图,很不错,我就懒得画了。

 

参考资料:

http://blog.sina.com.cn/s/blog_6488248f0100wu6v.html

http://blog.csdn.net/acs713/article/details/8575235

Linux high memory 学习总结的更多相关文章

  1. Linux内存管理学习资料

    下面是Linux内存管理学习的一些资料. 博客 mlock() and mlockall() system calls. All about Linux swap space 逆向映射的演进 Linu ...

  2. Linux 目录结构学习与简析 Part1

    linux目录结构学习与简析 by:授客 QQ:1033553122 说明: /             linux系统目录树的起点 =============== /bin      User Bi ...

  3. Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号

    Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号 背景 上一讲我们介绍了Unix IPC中的2种管道. 回顾一下上一讲的介绍,IPC的方式通常有: Unix IPC包括:管道 ...

  4. Linux 系统编程 学习:04-进程间通信2:System V IPC(1)

    Linux 系统编程 学习:04-进程间通信2:System V IPC(1) 背景 上一讲 进程间通信:Unix IPC-信号中,我们介绍了Unix IPC中有关信号的概念,以及如何使用. IPC的 ...

  5. 20135231 —— Linux 基础入门学习

    20135231 何佳 学习计时:共12小时 读书:5 代码:2 作业:2 博客:3 一.学习目标 1. 能够独立安装Linux操作系统 2. 能够熟练使用Linux系统的基本命令 3. 熟练使用Li ...

  6. Linux系统新手学习的11点建议

    随着Linux应用的扩展许多朋友开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.这里介绍学习Linux的一些建议. 一.从基础开始:常常有些朋友在Linux论 ...

  7. Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

    Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

  8. Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

    Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

  9. Linux进程间通信IPC学习笔记之消息队列(SVR4)

    Linux进程间通信IPC学习笔记之消息队列(SVR4)

随机推荐

  1. 走进异步世界:EnyimMemcached异步化改造引起的内存泄漏

    6月30日我们发布了异步化改造后的博客程序之后,出现了高内存.高CPU.高线程数的不理想情况. 经过一周的追查,终于水落日出——引起不理想情况的根源是我们修改过的EnyimMemcached代码存在内 ...

  2. 项目中的web api知识总结

    最近在做公司的项目,自己负责webapi的框架的搭建与开发,最近很忙,一直没时间对工作中遇到的知识点缺少个总结,现总结一下,对自己是个提升,如果个人的小点点小总结能对博友有帮助那也是善莫大焉. (1) ...

  3. [修复] Firemonkey 使用 DrawPath 断线问题(Android & iOS 平台)

    问题:使用 Canvas.DrawPath 绘制时,最后一点无法画到终点位置.(这个问题要在粗线才能察觉) 适用:Delphi 10 Seattle (或更早的版本) for Android & ...

  4. FPGA中的delay与latency

    delay和latency都有延迟的意义,在FPGA中二者又有具体的区别. latency出现在时序逻辑电路中,表示数据从输入到输出有效经过的时间,通常以时钟周期为单位. delay出现在组合逻辑电路 ...

  5. SpringMVC框架介绍

     1. SpringMVC通过一套MVC注解,让POJO成为处理请求的控制器,而无须实现任何接口. 2.支持REST风格的URL请求. 3.采用了松散耦合可插拔组件结构,比其他MVC框架更具扩展性和灵 ...

  6. ahjesus使用T4模板自动维护实体

    在entity项目里新建模板DBEntity.tt <#@ template debug="false" hostspecific="true" lang ...

  7. Android开发中Eclispe相关问题及相应解决(持续更新)

    1.Eclipse项目中的Android Private Libraries没有自动生成. 一般而言,在Android开发中,项目中引用到的jar包会放到项目目录中的libs中,引入库会放到Andro ...

  8. linux下MySQL表名忽略大小写设置

    最近公司项目的MySQL数据库要迁移到linux下,部署时日志总是显示报找不到一个表,用MYSQL查看明明有这个表.后来经百度,原来LINUX下的MYSQL默认是区分表名大小写的. 用命令查看当前是否 ...

  9. 七个结构模式之适配器模式(Adapter Pattern)

    定义: 将一个接口转换为客户需要的另外一个接口,使接口不兼容的类型可以一起工作,也被称为包装器模式(Wrapper Patern). 结构图: Target:目标抽象类,客户所需要的接口. Adapt ...

  10. SQLServer2008部署镜像

    SQL Server 2008 R2数据库镜像部署 概述 “数据库镜像”是一种针对数据库高可用性的基于软件的解决方案.其维护着一个数据库的两个相同的副本,这两个副本分别放置在不同的SQL Server ...