IT猫扑网:您身边最放心的安全下载站! 最新更新| 软件分类| 专题汇总| 手机版

您当前所在位置:IT猫扑网 > 操作系统 > LINUX > Linux高端内存

Linux高端内存

时间:2015-06-28 00:00 来源:IT猫扑网|http://www.itmop.com/ 作者:网管联盟 我要评论(0)

  高端内存是指物理地址大于 896M 的内存。

  对于这样的内存,无法在&内核直接映射空间&进行映射。

  为什么?

  因为&内核直接映射空间&最多只能从 3G 到 4G,只能直接映射 1G 物理内存,对于大于 1G 的物理内存,无能为力。

  实际上,&内核直接映射空间&也达不到 1G, 还得留点线性空间给&内核动态映射空间& 呢。

  因此,Linux 规定&内核直接映射空间& 最多映射 896M 物理内存。

  对 于高端内存,可以通过 alloc_page() 或者其它函数获得对应的 page,但是要想访问实际物理内存,还得把 page 转为线性地址才行(为什么?想想 MMU 是如何访问物理内存的),也就是说,我们需要为高端内存对应的 page 找一个线性空间,这个过程称为高端内存映射。

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

  1、映射到&内核动态映射空间&

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

  2、永久内核映射

  如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?

  内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START ,用于映射高端内存。在 2.4 内核上,这个地址范围是 4G-8M 到 4G-4M 之间。这个空间起叫&内核永久映射空间&或者&永久内核映射空间&

  这个空间和其它空间使用同样的页目录表,对于内核来说,就是 swapper_pg_dir,对普通进程来说,通过 CR3 寄存器指向。

  通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。

  通过 kmap(), 可以把一个 page 映射到这个空间来

  由于这个空间是 4M 大小,最多能同时映射 1024 个 page。因此,对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来。

  3、临时映射

  内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为&固定映射空间&

  在这个空间中,有一部分用于高端内存的临时映射。

  这块空间具有如下特点:

  1、 每个 CPU 占用一块空间

  2、 在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的 km_type中。

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

  通过 kmap_atomic() 可实现临时映射。

  下图简单简单表达如何对高端内存进行映射

  -------------------------

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

  从 PAGE_OFFSET开始的线性地址区域为:

  PAGE_OFFSET(3G)|物理内存映射 --8M-- vmalloc区 --4K-- vmalloc区 --8K-- 永久内核映射--临时内核映射(固定映射)|4G

  1. 非连续区映射

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

  1.2 三种非连续区的类型:

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

  VM_MAP     -- 仅申请线性区,物理内存另外申请,是VM_ALLOC的简化版

  VM_IOREMAP -- 仅申请线性区,物理内存另外申请(这里的物理内存一般都是高端内存,大于896M的内存)

  2. 永久内核映射

  2.1 永久内存映射允许建立长期映射。使用主内核页表中swapper_pg_dir的一个专门页表。

  pkmap_page_table: 专门的页表。页表表项数由LAST_PKMAP(512或1024)产生。

  page_address_htable: 存放地址的

  pkmap_count: 包含LAST_PKMAP个计数器的数组。

  PKMAP_BASE: 页表线性地址从PKMAP_BASE开始。

  2.2 如果LAST_PKMAP个项都用完,则把当前进程置为 TASK_UNINTERRUPTIBLE,并调用schedule()

  3. 临时内存映射

  3.1 可以用在中断处理函数和可延迟函数的内部,从不阻塞。因为临时内存映射是固定内存映射的一部分,一个地址固定给一个内核成分使用。

  3.2 每个CPU都有自己的一个13个窗口(一个线性地址及页表项)的集合。

  enum km_type {

  KM_BOUNCE_READ,

  KM_SKB_SUNRPC_DATA,

  KM_SKB_DATA_SOFTIRQ,

  KM_USER0,

  KM_USER1,

  KM_BIO_SRC_IRQ,

  KM_BIO_DST_IRQ,

  KM_PTE0,

  KM_PTE1,

  KM_IRQ0,

  KM_IRQ1,

  KM_SOFTIRQ0,

  KM_SOFTIRQ1,

  KM_TYPE_NR

  };

  所有固定映射的固定线性地址

  enum fixed_addresses {

  FIX_HOLE,

  FIX_VSYSCALL,

  ....

  #ifdef CONFIG_HIGHMEM

  FIX_KMAP_BEGIN,    /* reserved pte's for temporary kernel mappings */

  FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,

  #endif

  .......

  __end_of_permanent_fixed_addresses,

  /* temporary boot-time mappings, used before ioremap() is functional */

  #define NR_FIX_BTMAPS    16

  FIX_BTMAP_END = __end_of_permanent_fixed_addresses,

  FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,

  FIX_WP_TEST,

  __end_of_fixed_addresses

  };

  3.3 注意 fixed_addresses 的地址从上至下是倒着的,FIX_HOLE的地址等于 0xfffff000,是一个洞

  #define __fix_to_virt(x)    (FIXADDR_TOP - ((x) << PAGE_SHIFT))

  #define __FIXADDR_TOP    0xfffff000

  -------------------------

  VMALLOC_RESERVE和896M

  LINUX 内核虚拟地址空间到物理地址空间一般是固定连续影射的。

  假定机器内存为512M,

  从 3G开始,到3G + 512M 为连续固定影射区。zone_dma, zone_normal为这个区域的。固定影射的VADDR可以直接使用(get a free page, then use pfn_to_virt()等宏定义转换得到vaddr)或用kmalloc等分配. 这样的vaddr的物理页是连续的。得到的地址也一定在固定影射区域内。

  如果内存紧张,连续区域无法满足,调用vmalloc分配是必须的,因为它可以将物理不连续的空间组合后分配,所以更能满足分配要求。vmalloc可以映射高端页框,也可以映射底端页框。vmalloc的作用只是为了提供逻辑上连续的地址。。。

  但 vmalloc分配的vaddr一定不能与固定影射区域的vaddr重合。因为vaddr到物理页的影射同时只能唯一。所以vmalloc得到的 vaddr要在3G + 512m 以上才可以。也就是从VMALLOC_START开始分配。 VMALLOC_START比连续固定影射区大最大vaddr地址还多8-16M(2*VMALLOC_OFFSET)--有个鬼公式在

  #define VMALLOC_OFFSET   8*1024

  #define VMALLOC_START   (high_memory - 2*VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)

  high_memory 就是固定影射区域最高处。

  空开8-16M做什么? 为了捕获越界的mm_fault.

  同样,vmalloc每次得到的VADDR空间中间要留一个PAGE的空(空洞),目的和上面的空开一样。你vmalloc(100)2次,得到的2个地址中间相距8K。

  如果连续分配无空洞,那么比如

  p1=vmalloc(4096);

  p2=vmalloc(4096);

  如果p1使用越界到p2中了,也不会mm_falut. 那不容易debug.

  下面说明VMALLOC_RESERVE和896M的问题。

  上面假设机器物理512M的case. 如果机器有1G物理内存如何是好?那vmalloc()的vaddr是不是要在3G + 1G + 8M 空洞以上分配?超过寻址空间了吗。

  这时,4G 下面保留的VMALLOC_RESERVE 128m 就派上用场了。

  也就是说如果物理内存超过896M, high_memory也只能在3G + 896地方。可寻址空间最高处要保留VMALLOC_RESREVE 128M给vmalloc用。

  所以这128M的VADDR空间是为了vmalloc在物理超过了896M时候使用。如果物理仅仅有512M, 一般使用不到。因为VMALLOC_START很低了。如果vmalloc太多了才会用到。

  high_memory在arch/i386/kernel, mm的初始化中设置。根据物理内存大小和VMALLOC_RESERVE得到数值.

  所以说那128M的内核线性地址仅仅是为了影

关键词标签:Linux

相关阅读 安装红帽子RedHat Linux9.0操作系统教程 Tomcat9.0如何安装_Tomcat9.0环境变量配置方法 多种操作系统NTP客户端配置 Linux操作系统修改IP Linux实现SCSI硬盘热插拔及在线识别 Linux下用CDMA modem拨号上网

文章评论
发表评论

热门文章 安装红帽子RedHat Linux9.0操作系统教程 安装红帽子RedHat Linux9.0操作系统教程 Linux服务器:设计高性能网站架构-LLMP Linux服务器:设计高性能网站架构-LLMP 使用Clonezilla迁移到虚拟Linux环境 使用Clonezilla迁移到虚拟Linux环境 Linux上的MRTG流量监控中心 Linux上的MRTG流量监控中心 Linux 双网卡绑定一个IP原理及实现 Linux 双网卡绑定一个IP原理及实现 linux和windows等系统远程控制ubuntu桌面 linux和windows等系统远程控制ubuntu桌面

相关下载

人气排行 Linux下获取CPUID、硬盘序列号与MAC地址 dmidecode命令查看内存型号 linux tc实现ip流量限制 安装红帽子RedHat Linux9.0操作系统教程 linux下解压rar文件 lcx.exe、nc.exe、sc.exe入侵中的使用方法 Ubuntu linux 关机、重启、注销 命令 查看linux服务器硬盘IO读写负载 linux命令行浏览器的使用方法 Linux NFS服务固定端口及防火墙配置 U盘安装Ubuntu 10.04 Linux清除用户登录记录和命令历史方法