linux 高端内存映射方式(精选3篇)
篇1:linux 高端内存映射方式
1.1 内核地址空间(线性空间)分布
(1) 直接映射区:线性空间中从3G开始最大896M的区间,为直接内存映射区,该区域的线性地址和物理地址存在线性转换关系:线性地址=3G+物理地址,
linux 高端内存映射方式
。
(2) 动态内存映射区:该区域由内核函数vmalloc来分配,特点是:线性空间连续,但是对应的物理空间不一定连续。vmalloc分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。
(3) 永久内存映射区:该区域可访问高端内存。访问方法是使用alloc_page(_GFP_HIGHMEM)分配高端内存页或者使用kmap函数将分配到的高端内存映射到该区域。
(4) 固定映射区:该区域和4G的顶端只有4k的隔离带,其每个地址项都服务于特定的用途,如ACPI_BASE等。
说明:
注意用户空间当然可以使用高端内存,而且是正常的使用,内核在分配那些不经常使用的内存时,都用高端内存空间(如果有),所谓不经常使用是相对来说的,比如内核的一些数据结构就属于经常使用的,而用户的一些数据就属于不经常使用的。用户在启动一个应用程序时,是需要内存的,而每个应用程序都有3G的线性地址,给这些地址映射页表时就可以直接使用高端内存。
而且还要纠正一点的是:那128M线性地址不仅仅是用在这些地方的,如果你要加载一个设备,而这个设备需要映射其内存到内核中,它也需要使用这段线性地址空间来完成,否则内核就不能访问设备上的内存空间了。
总之,内核的高端线性地址是为了访问内核固定映射以外的内存资源。进程在使用内存时,触发缺页异常,具体将哪些物理页映射给用户进程是内核考虑的事情。在用户空间中没有高端内存这个概念。
1.2 高端内存映射
高端内存映射含义为:将线性地址空间 (范围从PAGE_OFFSET + 896M 至4G的最后128M)映射到 896M以上的物理页框。如下图所示:
高端内存映射有三种方式(都是非直接映射):
1.2.1 映射到“内核动态映射空间”(非连续内存区映射)
这种方式很简单,因为通过 vmalloc ,在内核“动态映射空间”申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说高端内存有可能映射到“内核动态映射空间 ”中,
1.2.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 对应的线性地址从这个空间释放出来。永久内存映射允许建立长期映射。
1.2.3 临时映射
内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为“固定映射空间”在这个空间中,有一部分用于高端内存的临时映射。
这块空间具有如下特点:
1、 每个 CPU 占用一块空间
2、 在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的 km_type 中。当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。
通过 kmap_atomic() 可实现临时映射。可以用在中断处理函数和可延迟函数的内部,从不阻塞。因为临时内存映射是固定内存映射的一部分,一个地址固定给一个内核成分使用。
篇2:linux 高端内存映射方式
对于这样的内存,无法在“内核直接映射空间”进行映射。
为什么?
因为“内核直接映射空间”最多只能从 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 之间。这个空间起叫“内核永久映射空间”或者“永久内核映射空间”
通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。
通过 kmap(), 可以把一个 page 映射到这个空间来
3、临时映射
内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为“固定映射空间”
在这个空间中,有一部分用于高端内存的临时映射。
这块空间具有如下特点:
当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。
通过 kmap_atomic() 可实现临时映射。
篇3:linux 高端内存映射方式
PC104是一种应用于嵌入式控制现场的工业计算机总线标准, 被IEEE协会定义为IEEE-P996.1。PC104产品凭借紧凑的外形、灵活的配置功能、成熟的标准体系结构和高可靠性, 广泛应用于商业、工业、航空以及军用等领域, 是嵌入式应用领域的主导解决方案。
GNU/Linux是一种自由和开放源码的类Unix操作系统, 广泛安装在各种计算机硬件设备中, 是世界上使用最多的一种类UNIX操作系统。
2 PC104总线接口设计
尽管PC104总线支持64KB的I/O端口, 也就是16条地址线, 但实际能提供给用户使用的地址空间被限制在1024个端口。通过查看设备管理器的输入/输出资源列表, 发现许多的端口已经被各种系统及配置资源占用, 留给用户可以直接使用的端口其实并不很充裕。
这些可以直接使用的端口, 对于许多使用某些固定地址的PC104板卡而言, 也不会有问题。但有些情况下, 用户希望拥有一段从零开始的连续地址空间, 比如连续的64K地址空间, 作为用户的局部地址空间, 这样的端口地址分配是无法满足要求的。如果采用单个端口经多级译码来实现用户空间地址, 则会严重影响系统的性能。
采用PC104总线提供的16位地址线SA0~SA15, 配合存储器读写信号线SMEMR#和SMEMW#, 就可以构成16位的用户的局部地址空间, 并且是从零开始的连续64KB的地址空间, 这在实际应用中非常有意义。
接口的硬件框图如图1所示。
3 Linux下的驱动实现
设备驱动程序用以沟通硬件和应用软件, 它封装了所有与硬件相关的特性, 向用户提供一个一致的编程接口。用户执行一组标准化的调用, 驱动程序使用内核提供的规范的文件系统接口, 将这些调用映射到实际的硬件设备操作上。在用户程序看来, 硬件设备只是个“文件”, 应用程序可以像操作普通文件一样对硬件设备进行操作。
3.1 驱动程序结构
Linux内核中有三类主要的设备文件类型:字符设备、块设备和网络设备。字符设备不需要缓冲, 直接读写设备, PC104接口应用是典型的字符设备。字符设备驱动程序结构如图2所示。
在Linux内核中, 使用cdev结构描述一个字符设备, dev_t成员定义设备号, cdev结构中的文件操作结构fi le_operations定义了字符设备驱动提供给虚拟文件系统的接口函数, 是虚拟文件系统的标准接口, 内核通过该接口访问设备驱动程序的函数。
fi le_operations结构中的函数指针成员是字符设备驱动程序设计的主体内容, 在用户程序进行open () 、write () 、read () 、close () 等系统调用时最终被转到fi le_operations结构中对应的函数指针上, fi le_operation结构定义如下:
多数情况下, 只需为上面结构中的少数方法编写服务程序, 其他均设为NULL即可, 本文主要讨论如何实现服务于PC104接口的int (*mmap) (struct file*filp, struct vm_area_struct*vma) 方法。
3.2 内存映射的实现
内存映射要完成的任务是将设备的地址空间映射到用户空间。通常用户空间不能直接访问设备, 但设备驱动程序通过实现fi le_operations结构中的mmap () 函数指针, 使得用户空间能够直接访问设备的物理地址。驱动程序中的mmap () 函数将在用户进行mmap () 系统调用时最终被调用。mmap () 实现了将用户空间的一段内存与设备内存关联, 当用户程序访问用户空间的这段地址范围时, 实际上会转化为对设备的访问。
用户空间的系统调用mmap () 的原型为:void*mmap (void*start, size_t length, int prot, int fl ags, int fd, off_t offset) ;驱动程序的fi le_operations结构中的mmap () 函数原型为:int (*mmap) (struct fi le*fi lp, struct vm_area_struct*vma) ;
当用户程序进行mmap系统调用时, 内核先在用户进程虚拟地址空间的MMAP区域分配一个尚未被映射的空闲的区域, 这个区域用一个struct vm_area_struct对象表示, 接着调用设备驱动程序中的mmap方法。驱动程序需要在mmap方法里将vma对象所代表的用户空间虚拟地址映射到对应的物理内存上。在mmap方法中, 采用Linux内核提供的remap_pfn_range () 函数建立目录表项的页面映射。mmap () 必须以PAGE_SIZE为单位进行映射, 因为内存映射只能以页为单位进行。
remap_pfn_range () 函数的原型为:int remap_pfn_range (struct vm_area_struct vma, u n s i g n e d l o n g a d d r, u n s i g n e d l o n g p f n, unsigned long size, pgprot_t prot) ;这个函数将把vma对象表征的一段虚拟地址, 即参数addr起始的大小为size的虚拟地址空间映射到pfn表示的一段连续的物理页面上, pfn是页框号。
一个典型的驱动程序只映射与其外围设备相关的一小段地址, 而不是映射全部地址。因此, 驱动程序向用户空间映射部分内存只需要使用偏移量。remap_pfn_range () 函数有一个限制, 它只能访问保留页和超出物理内存的物理地址。在Linux的内存映射中, 物理地址页被标记为“reserved”的, 表示内存管理对其不起作用, 是唯一可以安全映射到用户空间的内存页。
内存范围在640KB到1MB之间的384KB的内存空间, 在PC系统中被标记为“reserved”正好可以选取一块连续的64KB地址, 来实现用户空间映射, 代码如下:
通过页目录表项的方式将struct vm_area_struct对象所代表的虚拟地址空间映射到设备的存储空间。如此, 用户进程将可以直接访问设备的存储区, 从而提高系统性能。
3.3 驱动的加载和卸载
每一个字符设备驱动程序都必须有_init_module和_cleanup_module两个函数, 加载和卸载字符设备时内核会自动调用这两个函数。用cat/proc/devices查看设备号, 以及分配到这些设备号的设备名称, 可以从60~63、120~127、240~254范围内指定设备号和设备名称, 也可以动态申请设备号和设备名称。
设备驱动模块加载函数:
设备驱动模块卸载函数:
3.4 用户空间的驱动调用
用户程序中对设备的操作就像使用普通文件一样:
执行mmap系统调用, 映射设备地址空间
在用户空间操作设备地址, 相应的总线时序出现在设备地址空间。
解除内存映射, 关闭设备文件
4 结束语
连续的16位局部用户地址线所提供的地址空间, 能够满足大多数检测控制类的硬件应用。内存映射绕开了内核空间到用户空间的数据复制过程, 将用户空间地址直接映射到设备地址上, 提供给用户程序直接操作设备地址的能力, 提升了系统性能, 有很强的实用意义。
参考文献
[1]PC104 Specification version 2.6
[2]J.Corbet, A.Rubini&Greg.KH。Linux设备驱动程序 (第三版) [M].中国电力出版社, 2003.
[3]陈学松.深入Linux设备驱动程序内核机制[M].电子工业出版社, 2005.
[4]宋宝华.Linux设备驱动开发详解 (第2版) [M].人民邮电出版社, 2008.
相关文章:
图像映射01-13
热水锅炉的操作与管理01-13
参数映射方法01-13
分析戴尔电脑广告词 映射我们广告语设计01-13
服务标识映射服务器01-13
映射方法01-13
概念映射01-13
多-多映射01-13
科学研究中的美学功能01-13
混沌映射01-13