物理内存低于896M各个区到底是怎么映射的

简介:

在Linux内核空间里,有三种内存区,ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM。

在64位系统上,HIGHMEM是不存在的,只有在32位系统上才会有。

在32位系统上,高于896M的物理内存称为高端内存。

内核地址空间为 3G-4G。

3G ~ 3G+896M为直接映射区,也就是说物理地址和内核虚拟地址只差3G的偏移量,比如说,内核中某个变量地址为3G+24M,那么这个变量所在的物理地址必然是24M。

内核还剩下128M的地址空间,这些是干什么用的呢?因为物理地址可能高于1G,高于1G的地方在内核里无法直接寻址,那怎么办的,这128M就是用来映射高于896M部分的内存的。举个例子,

内核里某个变量的地址是3G+1000M,那么这个变量的物理地址一般不会是1000M,当然有这个可能,因为1000M也位于高端内存。内核需要为这128M空间建立映射关系,128M映射896M~64G的部分(最多64G,开启PAE)。

这128M又分成几个区:

低于896M的部分称为直接映射区,后面分为VMALLOC区,永久映射区,固定映射区。

#define VMALLOC_OFFSET (8*1024*1024) //VMALLOC区与直接映射区的间隙,为了捕捉越界

范围是VMALLOC_START到VMALLOC_END,中间的4K是为了把分配的每段内存隔开,就像用户层的malloc,中间会有间隙。

这个VMALLOC分配内存时,会把地址映射到这个区域,举个例子,假如你用vmalloc得到了1M内存,物理地址(假设连续,实际不一定)为22G~22G+1M,返回给你的地址有可能是920M~921M。kmalloc与vmalloc的区别之一就是kmalloc会在低端内存申请。

后面的PKMAP区和FIXMAP区用法是这样的,你得到了一个高端内存的page,需要在内核里读写,但是内核不能直接操作page,需要地址,这样你调用kmap或者kmap_atomic,会把这个page映射到这两个区。当然加入这个page来自低端内存,直接返回page_address()的结果。

有一个问题一直很困扰我,假入内存不到896M呢?实际上内存不到896M,照样可以使用vmalloc。

先来看个例子


 
 
  1. #include <linux/init.h>  
  2. #include <linux/module.h>  
  3. #include <linux/vmalloc.h>  
  4. static int hello_init(void)  
  5. {  
  6.         char *test;  
  7.         char *test1;  
  8.         test = vmalloc(8);  
  9.         test1 = kmalloc(8,0);  
  10.         printk(KERN_ALERT "%x,%d\n",test,(unsigned int)test/(1024*1024));  
  11.         printk(KERN_ALERT "%x,%d\n",test1,(unsigned int)test1/(1024*1024));  
  12.         vfree(test);  
  13.         kfree(test1);  
  14.         return 0;  
  15. }  
  16. static void hello_exit(void)  
  17. {  
  18.         printk(KERN_ALERT "Goodbye,cruel world!\n");  
  19. }  
  20. module_init(hello_init);  
  21. module_exit(hello_exit); 

内存256M:

内存512M:

 

内存1024M:

 

可见VMALLOC区不一定是在896M+8M到896M+8M+128M。

kmalloc返回的地址都在物理内存范围内,而vmalloc返回的地址就不一样了。我们再看上面各个区的分布图,发现有个high_memory,其实这是个变量,

上面是在物理内存为256的情况下打印high_memory,(除以1024*1024),可见这个high_memory是根据物理内存算出来的,具体代码如下


 
 
  1. #ifdef CONFIG_HIGHMEM  
  2.         highstart_pfn = highend_pfn = max_pfn;  
  3.         if (max_pfn > max_low_pfn)  
  4.                 highstart_pfn = max_low_pfn;  
  5.         e820_register_active_regions(0, 0, highend_pfn);  
  6.         sparse_memory_present_with_active_regions(0);  
  7.         printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",  
  8.                 pages_to_mb(highend_pfn - highstart_pfn));  
  9.         num_physpages = highend_pfn;  
  10.           high_memory = (void *) __va(highstart_pfn * PAGE_SIZE-1)+1;   
  11. #else  
  12.         e820_register_active_regions(0, 0, max_low_pfn);  
  13.         sparse_memory_present_with_active_regions(0);  
  14.         num_physpages = max_low_pfn;  
  15.          high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1)+1;   
  16. #endif  

VMALLOC_START在high_memory后面8M开始,一般应该是高于物理内存的。

我们来理清几个问题:

低于896M的物理内存与虚拟内存在内核空间里是一一对应的,这句话是有问题的,需要分情况说。

如果总得物理内存低于896M,假设为A,对于内核中的一个地址,如果小于A那么这个地址与物理地址只差一个偏移量,如果大于A,那么肯定位于VMALLOC区。如果一个物理地址为X的页被内存使用,即使X小于896,它对应的虚拟地址也有可能不是3G+896。

越写越乱,先写到这吧。



本文转自nxlhero 51CTO博客,原文链接:http://blog.51cto.com/nxlhero/711805,如需转载请自行联系原作者

相关文章
|
27天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
44 6
|
3月前
|
存储 缓存 Linux
用户态内存映射
【9月更文挑战第20天】内存映射不仅包括物理与虚拟内存间的映射,还涉及将文件内容映射至虚拟内存,使得访问内存即可获取文件数据。mmap 系统调用支持将文件或匿名内存映射到进程的虚拟内存空间,通过多级页表机制实现高效地址转换,并利用 TLB 加速映射过程。TLB 作为页表缓存,存储频繁访问的页表项,显著提升了地址转换速度。
|
2月前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
65 0
|
3月前
|
存储 安全 Linux
将文件映射到内存,像数组一样访问
将文件映射到内存,像数组一样访问
40 0
|
3月前
|
Linux Shell 虚拟化
使用LiME收集主机物理内存的内容时发生宕机
使用LiME收集主机物理内存的内容时发生宕机
|
3月前
crash —— 获取物理内存布局信息
crash —— 获取物理内存布局信息
|
3月前
|
消息中间件 Linux 容器
共享内存的创建和映射过程
【9月更文挑战第1天】消息队列、共享内存及信号量在使用前需生成key并获取唯一ID,均通过`xxxget`函数实现。
|
5月前
|
开发者 Java
JVM内存问题之top命令的物理内存信息中,'used'和'free','avail Mem'分别表示什么
JVM内存问题之top命令的物理内存信息中,'used'和'free','avail Mem'分别表示什么
|
6月前
|
监控 Linux
深入了解Linux的pmap命令:进程内存映射的利器
`pmap`是Linux下分析进程内存映射的工具,显示内存区域、权限、大小等信息。通过`/proc/[pid]/maps`获取数据,特点包括详细、实时和灵活。参数如`-x`显示扩展信息,`-d`显示设备。示例:`pmap -x 1234`查看进程1234的映射。注意权限、实时性和准确性。结合其他工具定期监控,排查内存问题。
|
7月前
|
算法 内存技术
深入理解操作系统内存管理:从虚拟内存到物理内存的旅程
【5月更文挑战第24天】 在现代计算机系统中,操作系统的内存管理是确保系统高效稳定运行的关键组成部分。本文将探讨操作系统是如何通过虚拟内存到物理内存的映射机制,实现对内存资源的高效管理和保护。我们将剖析分页和分段两种主要的内存管理技术,并讨论它们如何协同工作以提供内存抽象、重定位、共享和保护。文章还将涉及虚拟内存的技术细节,包括页面置换算法和内存分配策略,以及它们对系统性能的影响。