第11章 内存与IO访问之CPU与内存、I/O

本章知识点

Linux系统提供复杂的内存管理功能,内存的概念在Linux系统中相对复杂,有常规内存、高端内存、虚拟地址、逻辑地址、总线地址、物理地址、I/O内存、设备内存、预留内存等概念。

1、内存和I/O的硬件机制,主要涉及内存空间、I/O空间和MMU。

2、Linux的内存管理、内存区域的分布、常规内存与高端内存的区别。

3、Linux内存存取的方法,主要涉及内存动态申请以及通过虚拟地址存取物理地址的方法。

4、设备I/O端口和I/O内存的访问流程。

5、I/O内存静态映射。

6、设备驱动中的DMA与Cache一致性问题以及DMA的编程方法。

11.1 CPU与内存、I/O

11.1.1 内存空间与I/O空间

    在x86处理器中存在着I/O空间的概念,I/O空间是相对于内存空间而言的,IO空间通过特定的指令in、out来访问。端口号标识外设的寄存器地址。Intel语法中的in、out指令格式如下:

IN 累加器, {端口号│DX}
OUT {端口号│DX},累加器

    目前,大多数嵌入式微控制器(如ARM、PowerPC等)中并不提供I/O空间,仅存在内存空间。内存空间可以直接通过地址、指针来访问,程序及在程序运行中使用的变量和其他数据都存在于内存空间中。

    内存地址可以直接由C语言指针操作,在186处理器中执行如下代码:

unsigned char *p = (unsigned char *)0xF000FF00;

*p=11; 

上述语句表明在绝对地址0xF0000+0xFF00(186处理器使用16位段地址和16位偏移地址)中写入11。

而在ARM、PowerPC未采用段地址的处理器中,p指向的内存空间就是0xF000FF00,而*p=11就是在该地址写入11。

再如,186处理器启动后会在绝对地址0xFFFF0(对应的C语言指针是0xF000FFF0,0xF000为段地址,0xFFF0为段内偏移)中执行,下面的代码:

typedef void (*lpFunction) ( void);    /* 定义一个无参数、无返回类型的函数指针类型 */

lpFunction lpReset = (lpFunction)0xF000FFF0;/* 定义一个函数指针,指向CPU启动后所执行的第一条指令的位置  */
lpReset ();/*调用函数*/

上面程序中,没有定义任何一个函数实体,程序却执行了这样的函数调用:lpReset(),它实际上起到了“软重启”的作用,跳转到CPU启动后第一条要执行的指令的位置。因此,可以通过函数指针调用一个没有函数体的“函数”,本质上只是换一个地址开始执行。

即便在x86处理器中,虽然提供了I/O空间,如果由自己设计电路板,外设仍然可以只挂接在内存空间中。此时,CPU可以像访问一个内存单元那样来访问外设I/O端口,不需要设立专门的I/O指令。因此,内存空间是必需的,而I/O空间是可选的。图11.1给出内存空间和I/O空间的对比


图11.1 内存空间和I/O空间

11.1.2 内存管理单元

    高性能处理器一般会提供一个内存管理单元(MMU),MMU单元辅助操作系统进行内存管理,提供虚拟地址和物理地址的映射、内存访问权限保护和Cache缓存控制等硬件支持。操作系统内核借助MMU可以让用户感觉到程序好像可以使用非常大的内存空间,使得开发者在编写程序时不用考虑计算机中物理内存的实际容量。

为理解基本的MMU操作原理,需先明确几个概念。

1)TLB(Translation Lookaside Buffer):即转换旁路缓存TLB是MMU的核心部件,它缓存少量的虚拟地址与物理地址的转换关系,是转换表的Cache,经常被称为“快表”。

2)TTW(Translation Table walk):即转换表漫游,当TLB中没有缓冲对应的地址转换关系时,需要通过对内存中转换表(多数处理器的转换表为多级页表,如图11.2所示)的访问来获得虚拟地址和物理地址的对应关系。TTW成功后,结果应写入TLB中。


图11.2 内存中的转换表

图11.3给出一个典型的ARM处理器访问内存的过程,其他处理器也执行类似过程。当ARM要访问存储器时,MMU先查找TLB(转换旁路缓存)中的虚拟地址表。如果ARM的结构支持分开的数据TLB(DTLB)和指令TLB(ITLB),则除取指令使用ITLB外,其他的都使用DTLB。ARM处理器的MMU如图11.3所示。


图11.3 ARM处理器的MMU

    若TLB中没有虚拟地址的入口,则转换表遍历硬件并从存放于主存储器内的转换表中获取地址转换信息和访问权限(即执行转换表漫游(TTW)),同时将这些信息放入TLB,它或者被放在一个没有使用的入口或者替换一个已经存在的入口。之后,在TLB条目中控制信息的控制下,当访问权限允许时,对真实物理地址的访问将在Cache或者在内存中发生,如图11.4所示。


图11.4 ARM CPU进行数据访问的流程

    ARM内TLB条目中的控制信息用于控制对对应地址的访问权限以及Cache的操作。

    C(高速缓存)和B(缓冲)位被用来控制对应地址的高速缓存和写缓冲,并决定是否进行高速缓存。

    访问权限和域位用来控制读写访问是否被允许。如果不允许,MMU则向ARM处理器发送一个存储

器异常,否则访问将被允许进行。

    上述描述的MMU机制针对的是ARM处理器,但PowerPC、MIPS等其他处理器也均有类似的操作。

    MMU具有虚拟地址和物理地址转换、内存访问权限保护等功能,这将使得Linux操作系统能单独为系
统的每个用户进程分配独立的内存空间并保证用户空间不能访问内核空间的地址,为操作系统的虚拟内存

管理模块提供硬件基础。

    在Linux 2.6.11之前,Linux内核硬件无关层使用了三级页表PGD(Page Global Directory)、PMD(Page Middle Directory)和PTE(Page Table Entry);从Linux 2.6.11开始,为配合64位CPU的体系结构,硬件无关层则使用了4级页表目录管理的方式,即PGD(Page Global Directory)、PUD(Page Upper Directory)、PMD(Page Middle Directory)和PTE(Page Table Entry)。


猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/80429635