Linux设备驱动程序学习(20)-内存映射和DMA-基本概念

合集下载

Linux内核DMA机制-ShangShuWu

Linux内核DMA机制-ShangShuWu

Linux内核DMA机制-ShangShuWuDMA允许外围设备和主内存之间直接传输 I/O 数据, DMA 依赖于系统。

每一种体系结构DMA传输不同,编程接口也不同。

数据传输可以以两种方式触发:一种软件请求数据,另一种由硬件异步传输。

在第一种情况下,调用的步骤可以概括如下(以read为例):(1)在进程调用read 时,驱动程序的方法分配一个DMA 缓冲区,随后指示硬件传送它的数据。

进程进入睡眠。

(2)硬件将数据写入 DMA 缓冲区并在完成时产生一个中断。

(3)中断处理程序获得输入数据,应答中断,最后唤醒进程,该进程现在可以读取数据了。

第二种情形是在 DMA 被异步使用时发生的。

以数据采集设备为例:(1)硬件发出中断来通知新的数据已经到达。

(2)中断处理程序分配一个DMA缓冲区。

(3)外围设备将数据写入缓冲区,然后在完成时发出另一个中断。

(4)处理程序利用DMA分发新的数据,唤醒任何相关进程。

网卡传输也是如此,网卡有一个循环缓冲区(通常叫做 DMA 环形缓冲区)建立在与处理器共享的内存中。

每一个输入数据包被放置在环形缓冲区中下一个可用缓冲区,并且发出中断。

然后驱动程序将网络数据包传给内核的其它部分处理,并在环形缓冲区中放置一个新的 DMA 缓冲区。

驱动程序在初始化时分配DMA缓冲区,并使用它们直到停止运行。

DMA控制器依赖于平台硬件,这里只对i386的8237 DMA控制器做简单的说明,它有两个控制器,8个通道,具体说明如下:控制器1: 通道0-3,字节操作, 端口为 00-1F控制器2: 通道 4-7, 字操作, 端口咪 C0-DF- 所有寄存器是8 bit,与传输大小无关。

- 通道 4 被用来将控制器1与控制器2级联起来。

- 通道 0-3 是字节操作,地址/计数都是字节的。

- 通道 5-7 是字操作,地址/计数都是以字为单位的。

- 传输器对于(0-3通道)必须不超过64K的物理边界,对于5-7必须不超过128K边界。

linux中的MMAP和DMA

linux中的MMAP和DMA

PTRS_PER_PTE 每个页表的大小。两级处理器置 PTRS_PER_PMD 为 1,以避免处理中级。 unsigned long pgd_bal(pgd_t pgd) unsigned long pmd_val(pmd_t pmd) unsigned long pte_val(pte_t pte) 这三个宏被用来从有类型数据项中获取无符号长整数值。 这些宏通过在源码中使用严格 的数据类型有助于减小计算开销。 pgd_t *pgd_offset(struct mm_struct *mm,unsigned long address) pmd_t *pmd_offset(pgd_t *dir,unsigned long address) pte_t *pte_offset(pmd_t *dir,unsigned long address) 这些线入函数是用于获取与 address 相关联的 pgd,pmd 和 pte 项。 页表查询从一个指向 结构 mm_struct 的指针开始。与当前进程内存映射相关联的指针是 current->mm。指向 核心空间的指针由 init_mm 描述,它没有被引出到模块,因为它们不需要它。两级处理 器定义 pmd_offset(dir,add)为(pmd_t� )dir,这样就把 pmd 折合在 pgd 上。扫描页表的函 数总是被声明为 inline,而且编译器优化掉所有 pmd 查找。 unsigned long pte_page(pte_t pte) 这个函数从页表项中抽取物理页的地址。 使用 pte_val(pte)并不可行, 因为微处理器使用 pte 的低位存贮页的额外信息。这些位不是实际地址的一部分,而且需要使用 pte_page 从页表中、抽取实际地址。 pte_present(pte_t pte) 这个宏返回布尔值表明数据页当前是否在内存中。这是访问 pte 低位的几个函数中最常 用的一个——这些低位被 pte_page 丢弃。有趣的是注意到不论物理页是否在内存中, 页表始终在(在当前的 Linux 实现中) 。这简化了核心代码,因为 pgd_offset 及其它类似 函数从不失败;另一方面,即使一个有零“驻留存贮大小”的进程也在实际 RAM 中保 留它的页表。 仅仅看看这些列出的函数不足以使你对 Linux 的内存管理算法熟悉起来; 实际的内存管理要 复杂的多,而且还要处理其它一些繁杂的事,如高速缓存一致性。不过,上面列出的函数足 以给你一个关于页面管理实现的初步印象;你可以从核心源码的 include/asm 和 mm 子树中 得到更好的信息。

内存映射和DMA

内存映射和DMA

内存映射和DMA——Linux 的内存管理内存映射和DMA——Linux 的内存管理地址类型:用户虚拟地址:这是用户空间程序能看到的常规地址。

物理地址: 该地址在处理器和系统内存之间使用总线地址:该地址在外设总线和内存之间使用内核逻辑地址:组成了内核的常规地址空间。

该地至映射了部分内存,并经常被视为物理地址,在大多数体系结构中,逻辑地址与相关的物理地址的不同,仅仅在于它们之间相差一个固定的偏移量。

逻辑地址通常保存在UNSIGNED LONG ,和void*这样的内存变量中,用kmalloc返回的内存地址,就是内核逻辑地址内核虚拟地址:与逻辑地址相比,它与物理地址的映射不是线性和一一对应的。

所有的逻辑地址都是虚拟地址,而虚拟地址不一定是逻辑地址。

虚拟地址通常保存在指针变量中。

物理地址和页:物理地址被分为很多离散单元称为页,ARM中一个页的大小为4096字节/* PAGE_SHIFT determines the page size */#define PAGE_SHIFT 12 移动12位即得页帧数#define PAGE_SIZE (1UL 低端内存:存在于内核空间上的逻辑地址内存高端内存:指那些不存在逻辑地址的内存,它们处于内核虚拟地址之上内存映射和页结构:在高端内存中将无法使用逻辑地址,内存中处理内存的函数使用page结构的指针page结构中与驱动相关的成员:atomic—t count;对该页的访问计数void *virtual:如果该页被预设,则指向该页的虚拟地址,否则为NULL。

内核中维护一个或多个page数组,用来跟踪系统中的物理内存。

PAGE结构指针与虚拟地址之间的转换相关的宏:struct page *virt_to_page(void *kaddr);用来负责将逻辑地址转换为相应的page结构指针struct page *pfn_to_page(int pfn);通过给定的页祯号,返回page结构指针void *page_address(struct page*page)如果地址的话,返回该页的虚拟地址。

内存及DMA

内存及DMA

用I/O命令访问PCI总线设备配置空间pio_len = pci_resource_len (pdev, 0);mmio_start = pci_resource_start (pdev, 1);mmio_end = pci_resource_end (pdev, 1);mmio_flags = pci_resource_flags (pdev, 1);mmio_len = pci_resource_len (pdev, 1);这样看来0号bar就是提供的io映射,1号bar提供内存映射。

所以我想如果自己写一个以太网驱动的话,关于这块的代码就可以精简一下,只使用内存映射的方法就可以了。

下面是网上有人写的几种不同方式测试代码,他这些代码应该是在x86上试的,我没有试过,先分析,周末搞到arm上去跑一下。

[第一种]unsigned long mmio_start, addr1, addr2;void __iomem *ioaddr;mmio_start = pci_resource_start( pdev, 1);ioaddr = pci_iomap(pdev, 1, 0);addr1 = ioread32( ioaddr );addr2 = ioread32( ioaddr + 4 );printk(KERN_INFO "mmio start: %lX\n", mmio_start);printk(KERN_INFO "ioaddr: %p\n", ioaddr);printk(KERN_INFO "%02lX.%02lX.%02lX.%02lX.%02lX.%02lX\n",(addr1) & 0xFF,(addr1 >> 8) & 0xFF,(addr1 >> 16 ) & 0xFF,(addr1 >> 24 ) & 0xFF,(addr2) & 0xFF,(addr2 >> 8) & 0xFF );运行结果:Mar 10 22:34:56 localhost kernel: mmio start: E0000800Mar 10 22:34:56 localhost kernel: ioaddr: f8aa6800Mar 10 22:34:56 localhost kernel: 00.02.3F.AC.41.9D------------------------------------------------------------------------------------------------这种方法采用内存映射的方法,得到bar1的物理地址,mmio_start然后由pci_ioremap函数把bar1的这段地址映射到内核虚拟地址空间。

内存映射和DMA———vm_area_struct结构

内存映射和DMA———vm_area_struct结构

内存映射和DMA——vm_area_struct结构vm_area_struct结构在设备驱动中对mmp的实现中会用到。

为了优化查找方法,内核维护了VMA的链表和树型结构,vm_area-struct中很多成员函数都是用来维护这个结构的。

因此在驱动程序中不能随意创建VMA,或者打破这种组织结构。

VMA的作用是用于管理进程地址空间中不同区域的数据结构下面是这个结构体,红色部分标识了与驱动程序相关的部分,现在只能先做一个感性理解了,作为驱动工程师,应该是个实用主义者。

/** This struct defines a memory VMM memory area. There is one of these* per VM-area/task. A VM area is any part of the process virtual memory* space that has a special rule for the page-fault handlers (ie a shared* library, the executable area etc).*/struct vm_area_struct {struct mm_struct * vm_mm; /* The address space we belong to. */unsigned long vm_start; /* Our start address within vm_mm. */unsigned long vm_end; /* The first byte after our end addresswithin vm_mm. *//* linked list of VM areas per task, sorted by address */struct vm_area_struct *vm_next;pgprot_t vm_page_prot; /* Access permissions of this VMA. */unsigned long vm_flags; /* Flags, listed below. */描述该区域的一段标志,驱动程序最感兴趣的是VM—IO和VM—RESERVED。

linuxDMA接口知识点详解

linuxDMA接口知识点详解

linuxDMA接⼝知识点详解1.两种DMA映射类型1.1. ⼀致性DMA映射(Consistent DMA mappings )主要⽤于映射长时间使⽤的区域。

CPU和DMA controller不需要考虑cache的影响。

这⾥的consistent实际上是coherent的概念,不能保证consistent,也就是说需要memory barrier来保证memory order。

1.2 流式DMA映射(streaming DMA mapping)主要⽤于⼀次性DMA传输,传输完成后就会释放。

2.指定DMA设备的寻址范围include/linux/dma-mapping.h// ⽤于⼀致性内存映射的映射范围static inline int dma_set_coherent_mask(struct device *dev, u64 mask)// ⽤于流式内存映射的映射范围static inline int dma_set_mask(struct device *dev, u64 mask);3.DMA映射接⼝3.1⼀致性DMA接⼝分配较⼤DMA buffer// dev DMA控制器设备// size 要分配的DMA buffer⼤⼩// dma_handle 返回DMA buf的物理地址// flag 分配标志// 返回值 DMA buffer的虚拟地址void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)// dev DMA控制器设备// size 释放的DMA buffer⼤⼩// cpu_addr DMA buf的虚拟地址// dma_handle DMA buf的物理地址void dma_free_coherent(struct device *dev, size_t size,void *cpu_addr, dma_addr_t dma_handle)分配较⼩DMA buffer,从dma poll中申请。

linux内存映射相关知识点

linux内存映射相关知识点

linux内存映射相关知识点说明:此文档综合了网上很多文章,并结合自己的分析,综合《情景分析》。

里面的代码是网上的,尚未亲自验证,有时间了好好搞搞,若用版权问题,请及时通知,务必删除,谢谢。

1.外设内存资源通常,在系统运行时,外设的I/O内存资源的物理地址是已知的,由硬件的设计决定。

2.CPU对外设内存资源的访问对外部设备的访问有两种不同的形式:I/O映射方式(I/O-mapped)典型地,如X86处理器为外设专门实现了一个单独的地址空间,称为"I/O地址空间"或者"I/O端口空间",这个存储空间与内存分属两个不同的体系,CPU无法通过访问内存的指令而只能通过专门的I/O指令(如X86的IN和OUT指令)来访问这一空间中的地址单元;内存映射方式(Memory-mapped)RISC指令系统的CPU(如ARM、PowerPC等)通常只实现一个物理地址空间,外设I/O端口成为内存的一部分。

此时,CPU可以象访问一个内存单元那样访问外设I/O端口,而不需要设立专门的外设I/O指令。

3.Linux下对外设内存资源的操作需要注意:CPU并没有为这些已知的外设I/O内存资源的物理地址预定义虚拟地址范围;Linux下,驱动程序并不能直接通过物理地址访问I/O内存资源,而必须将它们映射到核心虚地址空间内(通过页表),然后才能根据映射所得到的核心虚地址范围,通过访问内存指令访问这些I/O内存资源;Linux在io.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地址映射到核心虚地址空间(3GB-4GB)中,原型如下:[cpp] view plaincopyprintstatic inline void __iomem * ioremap (unsigned longoffset, unsigned long size){ return__ioremap(offset, size, 0); } 在将I/O 内存资源的物理地址映射成虚地址后,理论上讲我们就可以象读写RAM那样直接读写I/O内存资源了。

Linux中关于MMAP and DMA的知识总结

Linux中关于MMAP and DMA的知识总结

3项技术:1,mmap系统调用可以实现将设备内存映射到用户进程的地址空间。

2,使用get_user_pages,可以把用户空间内存映射到内核中。

3,DMA的I/O操作,使得外设具有直接访问系统内存的能力。

-------------内存管理内核用来管理内存的数据结构---------地址内型Linux是一个虚拟内存系统,即用户程序使用的地址与硬件使用的物理地址是不等同的。

虚拟内存引入了一个间接层,使得许多操作成为可能:*有了虚拟内存,系统中运行的程序可以分配比物理内存更多的内存。

*虚拟地址还能让程序在进程的地址空间内使用更多的技巧,包括将程序的内存映射到设备内存上。

地址内型列表*用户虚拟地址每个进程都有自己的虚拟地址空间。

*物理地址处理器访问系统内存时使用的地址。

*总线地址在外围总线和内存之间使用。

MMU可以实现总线和主内存之间的重新映射。

当设置DMA操作时,编写MMU相关的代码是一个必需的步骤。

*内核逻辑地址内核逻辑地址组成了内核的常规地址空间,该地址映射了部分(或全部)内存,并经常被视为物理地址。

在大多数体系架构中,逻辑地址与其相关联的物理地址的不同,仅仅在于它们之间存在一个固定的偏移量。

kmalloc返回的内存就是内核逻辑地址。

*内核虚拟地址内核虚拟地址与逻辑地址相同之处在于,都将内核空间的地址映射到物理地址上。

不同之处在于,内核虚拟地址与物理地址的映射不是线性的和一对一的。

vmalloc返回一个虚拟地址,kmap函数也返回一个虚拟地址。

------------------物理地址和页物理地址被分为离散的单元,称之为页。

系统内部许多对内存的操作都是基于单个页的。

大多数系统都使用每页4096个字节,PAGE_SIZE <asm/page.h>给出指定体系架构下的页大小。

观察内存地址,无论是虚拟的还是物理的,它们都被分为页号和一个页内的偏移量。

如果每页4096个字节,那么最后的12位就是偏移量,剩余的高位则指定页号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux设备驱动程序学习(20)-内存映射和DMA-基本概念 (2011-09-25 15:47) 标签: 虚拟内存设备驱动程序Linux技术分类:Linux设备驱动程序
这部分主要研究 Linux 内存管理的基础知识, 重点在于对设备驱动有用的技术. 因为许多驱动编程需要一些对于虚拟内存(VM)子系统原理的理解。

而这些知识主要分为三个部分:
1、 mmap系统调用的实现原理:它允许设备内存直接映射到一个用户进程地址
空间. 这样做对一些设备来说可显著地提高性能.
2、与mmap的功能相反的应用原理:内核态代码如何跨过边界直接存取用户空间的内存页. 虽然较少驱动需要这个能力. 但是了解如何映射用户空间内存到内
核(使用 get_user_pages)会有用.
3、直接内存存取( DMA ) I/O 操作, 它提供给外设对系统内存的直接存取.
但所有这些技术需要理解 Linux 内存管理的基本原理, 因此我将先学习VM子
系统的基本原理.
一、Linux的内存管理
这里重点是 Linux 内存管理实现的主要特点,而不是描述操作系统的内存管理理论。

Linux虚拟内存管理非常的复杂,要写可以写一本书:《深入理解Linux 虚拟内存管理》。

学习驱动无须如此深入, 但是对它的工作原理的基本了解是必要的.
解了必要的背景知识后,才可以学习内核管理内存的数据结构.
Linux是一个虚拟内存系统(但是在没有MMU的CPU中跑的ucLinux除外), 意味着在内核启动了MMU 之后所有使用的地址不直接对应于硬件使用的物理地址,这些地址(称之为虚拟地址)都经过了MMU转换为物理地址之后再从CPU的内存总线中发出,读取/写入数据.
这样 VM 就引入了一个间接层, 它是许多操作成为可能: 1、系统中运行的程序可以分配远多于物理内存的内存空间,即便单个进程都可拥有一个大于系统的物理内存的虚拟地址空间. 2、虚拟内存也允许程序对进程的地址空间运用多种技巧, 包括映射程序的内存到设备内存.等等~~~
1、地址类型
Linux 系统处理几种类型的地址, 每个有它自己的含义:
用户虚拟地址:User virtual addresses,用户程序见到的常规地址. 用户地址在长度上是 32 位或者 64 位, 依赖底层的硬件结构, 并且每个进程有它自己
的虚拟地址空间.
总线地址:Bus addresses,在外设和内存之间使用的地址,但是这不是必要. 一些体系可提供一个 I/O 内存管理单元(IOMMU), 它在总线和主内存之间重映射地址.
物理地址:Physical addresses,在处理器和系统内存之间使用的地址. 有32bit 或64bit等。

以下的概念很重要,一定要理解了再往下看:
内核逻辑地址:Kernel logical addresses,他们是虚拟地址(需要经过MMU转换的地址),这些组成了常规的内核地址空间.这些地址映射了部分(也许全部)主存并且常常被当作物理内存. 在大部分的体系上, 逻辑地址和它们的相关物理地址只差一个常量偏移. 逻辑地址常常存储于 unsigned long 或者 void * 类型的变量中. 从 kmalloc 返回的内存就是内核逻辑地址.
内核虚拟地址:Kernel virtual addresses,它们都是从内核地址空间到物理地址的映射,但是内核虚拟地址并不必像逻辑地址空间一样具备线性的、一对一到物理地址的映射。

所有的逻辑地址是内核虚拟地址, 但是许多内核虚拟地址不是逻辑地址. (也就是说在启动MMU后所有的地址都是内核虚拟地址,但是有一部分可以称为内核逻辑地址,因为他们具有上面介绍的特性:线性且连续、与对应的物理地址只差一个常量偏移)
对于内核虚拟地址,vmalloc 分配的内存是虚拟地址. kmap 函数也返回虚拟地址. 虚拟地址常常存储于指针变量.
如果有内核逻辑地址, 可通过宏 __pa() ( 在 <asm/page.h> 中定义,但是也可能在它包含的头文件中)返回它关联的物理地址. 同时物理地址也可被映射回逻辑地址使用 __va(), 但是只适用于低端内存(后面会讲到).不同的内核函数需要不同类型地址.
2、物理地址和页
物理内存被划分为离散的单元称为页. 系统内部的许多内存处理都基于单个页. 页大小依赖体系结构, 大部分系统使用 4K字节为一页(ARM就是4KB/page). 在不同的体系上,常量 PAGE_SIZE (定义在 <asm/page.h>) 给出了页大小的具体定义.
1.物理内存会划分为固定大小的页来处理的原因,个人认为主要是由于MMU
的分页机制决定的(X86正常情况下MMU的页大小为4KB,ARM的MMU的
小页的页大小也是4KB)。

有的CPU的MMU分页的页大小是可调的,这可能使得内核配置的PAGE_SIZE也随之改变,比如MIPS构架的页大小可能
是4KB、8KB、16KB、32KB和64KB。

一个内存地址(虚拟或物理),它可分为一个页帧号和一个页内的偏移. 以使用4KB页为例, 低12 位有效位是偏移, 而剩下的高位为页帧号. 若忽略偏移并向右移动地址 offset 位, 结果即为页帧号 (PFN). 移位来在页帧号和地址之间转换是一个相当普通的操作. 宏 PAGE_SHIFT 告诉必须移动多少位来进行这个转换.
3、高端与低端内存
在拥有大量内存的 32bit系统中,内核逻辑地址和虚拟地址之间的差异就会突显出来。

32 bit 系统可寻址4G内存. 但是因为建立虚拟地址空间的限制(不能把所有虚拟地址空间都用完,必须留下一些作为临时的映射和IO空间映射之用),早
期的在 32bit Linux系统被限制使用少于4G的内存,比如我的DELL vostro 120笔记本,我升级到4G内存,原来的ubuntu 8.10 32bit只认到3G,且64bit根本装不上。

后来似乎是升级到了ubuntu 10.10 32bit才认到了4G内存。

内核(在x86体系的缺省配置里)划分4GB虚拟地址空间为用户空间和内核空间;在2个上下文中使用同一套映射.一个典型的划分:3GB用户空间-1GB内核空间。

内核的代码和数据结构必须要匹配这个空间,
占用内核地址空间最大部分的是物理内存的虚拟映射(包括逻辑地址映射和虚拟地址映射(如果有高端内存)). 内核不能直接操作没有映射到内核地址空间的内存. 换句话说, 内核对任何内存的访问需使用它自己的虚拟地址。

因此, 多年来, 能够被内核处理的最大物理内存量是能够映射到虚拟地址的内核部分的大小再减去内核代码自身的空间.因此,基于x86的Linux系统可以使用的最大内存量会比1GB稍小。

为了使用更多内存, 在不破坏 32bit应用和系统的兼容性的情况下,处理器制造商在产品中增加了"地址扩展"特性. 这样,即便32bit处理器也能够寻址多于4GB物理内存. 但可被直接用逻辑地址映射的内存大小限制还存在.这样内存的最低部分(根据硬件和内核配置一般是 1到2 GB, )有逻辑地址; 剩下的(高端内存)没有. 在访问一个特定高地址页前, 内核必须建立一个明确的虚拟映射来使此页可在内核地址空间中被访问. 因此, 许多内核数据结构必须放在低端内存; 高端内存主要为用户进程页所保留.
所以定义如下:
Low memory:低端内存
在内核空间中拥有逻辑地址的内存. 在大部分系统中(ARM构架几乎都是),几乎所有的内存都是低端内存.
High memory:高端内存
没有逻辑地址映射的内存,它位于内核逻辑地址范围之外,使用前必须使用vmalloc等内核函数做好映射.
在 i386 系统上, 低和高内存之间的分界在内核配置时可被改变,但常常设置在1GB以下。

这个边界与硬件无关.它是由内核自身设置的。

其实我认为这个分界线和两个内核配置因素有关:
(1)内核对于内核空间和用户空间比例的配置。

1GB :3GB、2GB :2GB、3GB :1GB等(例如比例是2GB :2GB,内核又有3G内存,则低端内存是可以超过1G的~~)(2)分配给内核虚拟地址空间的大小vmalloc,这个是可以在启动参数中设置的。

1.vmalloc=nn[KMG]
2.强制指定vmalloc区域的大小。

可用于增加vmalloc区域的最小尺寸(x86默认
128MB),也可以用于减少vmalloc的大小,增加更多的空间用于直接映射内核RAM。

当然硬件上的限制就是RAM的大小,低端内存和高端内存的和总不能超过RAM 总大小吧~~~
关于X86这方面的更详细的资料,我觉得可以参考以下链接:
linux的物理内存与线性地址空间布局--1
还有就是陈莉君老师的《解惑-linux内核空间(二)》
那么对于ARM构架来说,情况是一样的。

虽然说ARM构架中你很少能找到存在高端内存的设备,但是如果内存足够大(例如1GB、2GB的板子也不是没有,比如TI芯片DM8168的16路D1解决方案就用了1GB或2GB内存,当然其中一部分要分给视频协处理器和DSP),然后将vmalloc设置大些,也可以在系统中出现高端内存。

对于ARM构架,我稍微对内核的启动时的高低内存设置做了下跟踪,有兴趣的朋友可以看看:《Linux内核高-低端内存设置代码跟踪(ARM构架)》
最后对于LDD3的图,我感觉意思表达得不太好,自己画了一个。

我的理解是这样的,如果您觉得我错了,请指出来,先谢谢了!。

相关文档
最新文档