Linux内核 内存映射 & DMA

Linux Device Drivers, Third Edition [LWN.net]
第十五章 Memory Mapping and DMA

Address Types

Linux是一个虚拟内存系统,用户程序与硬件使用的物理地址不直接对应。虚拟内存引入了一层间接寻址,从而支持很多高级特性。通过虚拟内存,系统上可以给运行程序分配大于实际物理内存的内存空间;甚至,单个进程也可以拥有比物理内存大的虚拟地址地址空间。虚拟内存允许程序使用进程地址空间做一些高级操作,比如将程序内存映射到设备内存。

Linux系统有好几种类型的地址,每个地址都有自己的语义。但是,有时候内核不知道哪种情况下使用哪种类型的地址,因此程序员必须小心。

下面是Linux中使用的地址类型列表,以及于物理内存的关系。

  • User virtual addresses 用户虚拟地址
    用户空间程序看到的常规地址(regular addresses)。用户地址为32位或64位长度,具体取决于底层硬件架构,每个进程都有自己的虚拟地址空间。

  • Physical addresses 物理地址
    处理器和系统内存交互使用的地址。物理的地址是32位或64位的数量;某些情况下,32位系统也可以使用更大的物理地址。

  • Bus addresses 总线地址
    总线和内存交互使用的地址。通常,与处理器使用的物理地址相同,但也不一定。某些架构可以提供I/O内存管理单元(IOMMU),在总线和主存之间重新映射地址。IOMMU可以通过多种方式使得更简单,但必须在设置DMA时对IOMMU进行编程。总线地址,高度依赖架构。

  • Kernel logical addresses 内核逻辑地址
    这些组成了内核地址空间的normal部分。这些地址映射主内存的一部分(也许是全部),通常被视为物理地址。在大多数架构上,逻辑地址和它们关联的物理地址仅差一个固定的偏移量。逻辑地址使用硬件的原生指针大小,因此在32位系统上可能无法给所有的物理内存映射地址。逻辑地址通常存储在unsigned longvoid*类型的变量中。kmalloc返回的内存有一个内核逻辑地址。

  • Kernel virtual addresses 内核虚拟地址
    内核虚拟地址类似与逻辑地址,都是从内核空间地址到物理地址的映射。内核虚拟地址
    不一定是线性的、一对一的映射,这些是逻辑地址的特征。逻辑地址一定是内核地址虚拟地址,但内核虚拟地址不一定是逻辑地址。
    例如,vmalloc分配的内存有一个虚拟地址(不是直接到物理内存的映射)。kmap也返回虚拟地址。虚拟地址通常存储在指针变量中。

图片.png

Physical Addresses and Pages

物理内存被分成很多离散单元,称为页(page)。系统对内存的大部分内部处理基于页。页大小因架构而异,大多是4096-byte。常量PAGE_SIZE(定义在<asm/PAGE.h>)可以在任何架构上定义页大小。

如果查看地址(虚拟or物理),它被划分为一个页码(page number)和一个偏移量(offset)。如果使用4k页面,则低12位为偏移量,其余高位表示页码。

如果放弃该偏移并将其余向右移动,结果称为PFN(page frame number)。在PFN和地址之间转换是常见操作;宏PAGE_SHIFT告诉此转换须偏移多少位。

物理页通过Page Frame Number (PFN)识别。PFN可以从物理地址轻易计算出来,除以page size 或 去掉PAGE_SHIFT bits。

PFN计算:
PFN = (physical address / page frame size) 取整。余数是page frame offset。

通常,page frames大小等于virtual pages。

High and Low Memory

在32位系统上配备很多内存,逻辑地址和内核虚拟地址之间就差异明显了。使用32位,只可以寻址4 GB内存。
32位Linux系统因为其虚拟地址空间的设置方式,直到现在还被限制在比这少的内存上。

x86架构默认配置下,内核划分4GB虚拟地址空间给用户空间和内核空间;它们的contexts中使用相同的映射集。一个典型的划分方式:3 GB用于用户空间,1 GB用于内核空间。

内核的代码和data structures必须加载到该空间,但是使用内核地址空间最多的是到物理内存的虚拟映射。内核不能直接操作未映射到内核地址空间的内存。换句话说,内核需要它自己的虚拟地址来存放它必须直接接触的内存。
因此,多年来,内核可以处理的最大物理内存量是:可以映射到内核虚拟地址空间部分的内存量,减去内核代码本身所需的空间。所i有,x86 Linux 最多只可以使用略低于1GB的物理内存。

不破坏32位程序和系统兼容性,还能支持更多内存呢,就成了商业压力。为此,处理器制造商在产品中提供了地址扩展(address extension)功能。这样,32位处理器也可以寻址超过4GB的物理内存。

然而,可以被直接映射到逻辑地址的物理内存限制仍然存在。只有内存的最低位部分(最多1或2 GB,取决于硬件和内核配置)具有逻辑地址;其余的(高位内存)没有。在访问特定的高位内存页之前,内核必须设置显式虚拟映射,以使该页在内核地址空间中可用。

因此,许多内核data structures必须放在低位内存中;高位内存倾向于为用户空间进程页保留。

high memory一词可能会让一些人感到困惑,特别是因为它在PC世界中有其他含义。因此,我们在这里作术语定义:

  • Low memory
    在内核空间中存在逻辑地址的内存。几乎每个系统上,所有内存都是low memory。

  • High memory
    不存在逻辑地址的内存,因为它超出了为内核虚拟地址预留的地址范围。

在i386系统上,低位内存和高位内存之间的边界通常设置为略低于1GB,但是可以在内核配置更改。此边界仅于内核设置有关,与硬件无关。

Page Tables

现代系统,处理器都必须具备相应的机制将虚拟地址转换为物理地址制。该机制称为页表 (page table);本质上,它是一个多级树状数组,包含虚拟-物理的映射和一些相关的标志(flags)。Linux内核甚至在不直接使用页表的架构上,也维护着一组页表。

通常,设备驱动程序执行的许多操作都可能涉及到操作页表。幸运的是,2.6内核已经不再直接使用页表。
推荐阅读《Understanding The Linux Kernel》(O’Reilly),作者 Daniel P. Bovet and Marco Cesati 。

Virtual Memory Areas

VMA - 虚拟内存区域,是用于管理进程地址空间的不同区域的内核数据结构(kernel data structure)

VMA维护着进程虚拟内存中的一个由相同类型组成的区域:具有相同权限标志的,后端是同一对象(例如文件或交换空间)的,连续虚拟地址范围。

它大致上对应于segment(段)的概念,不过最好将其描述为“具有自身属性的内存对象”。进程的内存映射由(至少)以下区域组成:

  • 程序可执行代码的区域(通常称为文本 - text)

  • 多个数据区域,包括初始化数据(在执行开始时具有显式赋值的数据)、未初始化数据(BSS),和程序堆栈

  • 每个活动的内存映射一个区域

通过查看/proc/<pid/maps>可以看到进程的内存区域。/proc/self/proc/pid的特例,它对应当前进程。范例:

# cat /proc/1/maps   
               look at init
08048000-0804e000 r-xp 00000000 03:01 64652      /sbin/init  #text
0804e000-0804f000 rw-p 00006000 03:01 64652      /sbin/init  #data
0804f000-08053000 rwxp 00000000 00:00 0          #zero-mapped BSS
40000000-40015000 r-xp 00000000 03:01 96278      /lib/ld-2.3.2.so  #text
40015000-40016000 rw-p 00014000 03:01 96278      /lib/ld-2.3.2.so  #data
40016000-40017000 rw-p 00000000 00:00 0          #BSS for ld.so
42000000-4212e000 r-xp 00000000 03:01 80290      /lib/tls/libc-2.3.2.so  #text
4212e000-42131000 rw-p 0012e000 03:01 80290      /lib/tls/libc-2.3.2.so  #data
42131000-42133000 rw-p 00000000 00:00 0          #BSS for libc
bffff000-c0000000 rwxp 00000000 00:00 0          #Stack segment
ffffe000-fffff000 ---p 00000000 00:00 0          #vsyscall page

# rsh wolf cat /proc/self/maps  #### x86-64 (trimmed)
00400000-00405000 r-xp 00000000 03:01 1596291     /bin/cat    #text
00504000-00505000 rw-p 00004000 03:01 1596291     /bin/cat    #data
00505000-00526000 rwxp 00505000 00:00 0                       #bss
3252200000-3252214000 r-xp 00000000 03:01 1237890 /lib64/ld-2.3.3.so
3252300000-3252301000 r--p 00100000 03:01 1237890 /lib64/ld-2.3.3.so
3252301000-3252302000 rw-p 00101000 03:01 1237890 /lib64/ld-2.3.3.so
7fbfffe000-7fc0000000 rw-p 7fbfffe000 00:00 0                 #stack
ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0       #vsyscall
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容