Linux device driver 3 笔记 之 内存映射

来源:互联网 发布:linux下的jdk参数设置 编辑:程序博客网 时间:2024/06/06 18:29
今天自己学习 Linux设备驱动程序 第三版 第15章 内存映射和DMA. 感觉有点吃力。主要是对内存映射很多术语和概念不是很清楚,理解起来有点费劲。
后来结合英文原版,静下心来仔细学习,才算是有了一点进展。
现在在这里做一个笔记,以备以后复习用。

 

低端内存和高端内存
书中的图15-1有点误导人。图中将 内核虚拟地址 和 内核逻辑地址 分开了。其实应该是并在一起的。
内核虚拟地址 是 内核逻辑地址 的一个超集。 所有的内核逻辑地址都是内核虚拟地址。 但内核虚拟地址不一定是内核逻辑地址。

 

在32位系统中,用32位最大能表示4G内存。这4G就形成了虚拟地址的范围。内核将这4G做了一个划分。
一般将3G划给用户空间,1G划给内核空间。这1G就是所谓的内核地址空间。也就是1G内核虚拟地址。(注意前面说了,内核虚拟地址是内核逻辑地址的超集)
内核只能访问这1G的内核地址空间。对所有物理内存的访问,都必须映射到这1G内核地址空间。
在这1G内核地址空间中,有一部分地址是与物理地址具有一一对应关系的,他们之间只不过是差了一个固定的偏移量。
这部分地址就是内核逻辑地址了。也就是说内核逻辑地址与物理内存的映射是线性的。
而与内核逻辑地址对应的物理内存,或者说通过内核逻辑地址映射到物理内存,就是所谓的低端内存。

 

前面说了,内核地址空间只有1G,那其中的内核逻辑地址范围一定会略小于1G。那在配置了很大内存的系统中(超过1G),有部分内存就肯定无法通过内核逻辑地址来直接映射。
这部分无法通过内核逻辑地址来直接映射的内存就是 高端内存。

内核只能通过自己的1G的内核地址空间来访问内存。那要访问这些高端内存,就必须进行必要的映射。把高端内存映射到内核地址空间范围内。

引用Linux device driver 一书 第三版 第15章 中 kmap() 函数的介绍:
对于高端内存,kmap在专用的内核地址空间创建特殊的映射。对该种映射的数量是有限的。
也即是说,内核在内核地址空间(1G)中划分出一部分,专门用来映射高端内存。

等于说,这部分内核地址空间的地址是所有高端内存共享的。要用的时候,通过kmap进行映射,用完了,通过kunmap返还。

内存映射 和 page struct

提到page,想到的应该是物理内存。可以把page理解成物理内存的一个单位。内核不是以字节为单位来管理内存的,而是以页为单位来管理内存的。

所有的page,都是指物理内存。
因为内核地址空间无法直接表示所有的物理内存,所以仅通过一个内存地址无法代表一个物理内存。为了在内存中对物理内存进行抽象,就使用page这个结构体。
可以说,page结构体是内核中对所物理内存的一个抽象。所有物理内存中的一个页,都有一个page结构体的实例与之对应。拿到一个page结构体实例,你应该要意识到,这是一页物理内存。

内核维护了page结构体的数组,来跟踪系统中的物理内存。

虚拟内存区 (VMA)
其实就是段啦。代码段,数据段之类的。就是一片内存区域,在这片区域中的内存具有相同的一些属性,这些属性包括但不限于 权限,owner之类。在进行mmap操作时,其实就是要创建这样一个虚拟的内存区域(VMA)。