Linux内核剖析 之 内存寻址(二)

//接前一篇博客:

本节主要介绍硬件中分页机制。

4、线性地址->物理地址(分页:硬件部分)

       为了效率,线性地址被分成以固定长度为单位的组,称为页(Page),页内部连续的线性地址被映射到连续的物理地址中。

      分页单元把所有的内存分成固定长度的页框(page frame)。每个页框包含一个页(page),也就是说一个页框的长度与一个页的长度一致。页框是主存的一部分,因此是一个存储区域。页和页框是不同的,也只是一个数据块,可以存放在任何页框或磁盘中。

4.1、分页

      从80386起,Intel处理器的分页单元处理4KB的页。

      32位线性地址被分成3个域:

      *Directory(目录):最高10位

      *Table(页表):中间10位

      *Offset(偏移量):最低12位

      线性地址的转换分两步完成:

      *页目录表转换;

      *页表转换。

      使用二级模式的目的在于减少每个进程页表所需内存的数量。

 

      控制寄存器cr3中存放正在使用的页目录的物理地址。线性地址内的Directory字段决定页目录中的目录项,而目录项指向适当的页表。地址的Table字段依次又决定页表中的表项,而页表含有页所在页框的物理地址。Offset字段决定页框内的相对位置。由于Offset字段是12位长,故每一页含有4096B的数据。

      页目录项和页表项具有相同的结构,每项包含下面的字段

      *Present标志:

      置1,所指页或页表在主存中;为0,不在主存中。如果当访问一个地址时,页目录项或页表项的Present标志为0,则分页单元将该线性地址存放在寄存器cr2中,产生14号异常:缺页异常。

      *Field 标志:

      20位,页目录项中的Field指向包含一个页表的页框。页表项中的Field指向包含一页数据的页框。

      *PCD/PWT 标志:控制硬件高速缓存处理页或页表的方式。

      *Accessed 标志:每当分页单元对相应页框进行寻址时,设置这个标志。分页单元从来不重置这个标志,而是必须由操作系统去做。

      *Dirty 标志:只应用于页表项中,每当对一个页框写操作时就设置。分页单元从来不重置这个标志,而是必须由操作系统去做。

      *Read/Write:页或页表的存取权限。与段的3种存取权限(读、写、执行)不同的是,页的存取权限只有两种(读、写)。如果Read/Write标志为0,说明相应的页表或页是只读的,否则是可读写的。

      *User/Supervisor:访问页或页表所需的特权级。若此标志为0,只有当CPL小于3(Linux:CPU处于内核态)时才能对页寻址,否则总能对页寻址。

      *Page Size:只应用于页目录项。设置为1,则页目录项指向2M或4M的内存。(hugepage)

      *Global标志:只应用于页表项,用于防止常用页(全局页)从TLB中刷新出去。(当cr4寄存器的PGE(页全局启用)标志置位时,这个标志才有效)。

      ##扩展分页:(页框大小为4MB而不是4KB)

      ——通过设置cr4处理器寄存器的PSE标志能使扩展分页与常规分页共存。

 

     对于2M页面,启动时传递内核参数

hugepages=1024 

     对于1GB的页面:

default_hugepagesz=1G hugepagesz=1G hugepages=4

    CPU所支持的hugepage大小可以由cpu标志得知

If pse exists, 2M hugepages are supported; if pdpe1gb exists, 1G hugepages are supported.

For 2 MB pages, there is also the option of allocating hugepages after the system has booted.

echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

 

mkdir /mnt/huge

mount -t hugetlbfs nodev /mnt/huge

     
只要是在 /mnt/huge/ 目录下创建的文件,将其映射到内存中时都会使用 2MB 作为分页的基本单位。值得一提的是,hugetlbfs 中的文件是不支持读 / 写系统调用 ( 如read()或write()等 ) 的,一般对它的访问都是以内存映射的形式进行的。

    
在实际应用中,为了使用大页面,还需要将应用程序与库libhugetlb链接在一起。libhugetlb库对malloc()/free()等常用的内存相关的库函数进行了重载,以使得应用程序的数据可以放置在采用大页面的内存区域中,以提高内存性能。

      ##物理地址扩展(PAE)分页机制:

      物理地址扩展(Physical Address Extension,PAE)用于将32位线性地址转换为36位物理地址。

      通过设置cr4控制寄存器中的PAE标志激活PAE。

      PAE分页机制:

      *64GB的RAM被分为2^24个页框,页表项的物理地址字段从20位扩展到了24位。一个4KB的页表包含512个表项而不是1024个表项。

      *引入页目录表指针表(Page Directory Pointer Table,PDPT)的页表新级别,它由4个64为表项组成。

      *cr3控制寄存器包含一个27为的页目录指针表(PDPT)基地址字段。

      *当把线性地址映射到4KB的页时,32位线性地址按下列方式解释:

      Cr3:指向一个PDPT;

      位31-30:指向PDPT中4个项的一个;

      位29-21:指向页目录表中512个项中的一个;

      位20-12:指向页表中512项中的一个;

      位11-0:4KB页中的偏移量。

     *当把线性地址映射到2MB的页时,32位线性地址按下列方式解释:

      Cr3:指向一个PDPT;

      位31-30:指向PDPT中4个项的一个;

      位29-21:指向页目录表中512个项中的一个;

      位20-0:2MB页中的偏移量。

4.2 加快线性地址转换

      为了缩小CPU和RAM之间的速度不匹配,引入了硬件高速缓存。基于局部性原理。

      #cache line :高速缓存与内存间一次传输数据的长度。

      #PCD 当访问该页框中数据时,高速缓存功能被启用还是禁用。

      #PWT:当数据被写到页框时,采用通写策略还是回写策略。

      Linux对所有页框都启用高速缓存,对写操作都采用回写策略。

 

      TLB(Translation Lookaside Buffer):转换后援缓冲器。

      在多处理器系统中,每个CPU都有自己的TLB,称为本地TLB。

      机制:当一个线性地址第一次使用时,通过慢速访问RAM的页表计算出相应的物理地址,同时,该物理地址被存放在一个TLB表项(TLB Entry)中,以便以后对同一线性地址的引用可以快速地转换。

时间: 2024-11-01 03:07:03

Linux内核剖析 之 内存寻址(二)的相关文章

Linux内核剖析 之 内存寻址(三)

//接前一篇博客: 本节主要讲述Linux中的分页机制,注意对比Linux和80x86下分页机制的不同. 5.Linux中的分页                  图:Linux分页模式(四级页表)        Linux的进程处理很大程度上依赖于分页,每个进程都有自己的页全局目录和自己的页表集. 5.1.线性地址字段:       下列宏简化了页表处理.(80x86)       PAGE_SHIFT:       指定Offset字段的位数:当用于80x86处理器时,其值为12.     

Linux内核剖析 之 内存寻址(一)

1.内存地址 逻辑地址(Logical Address):包含在机器语言中用来指定一个操作数或一条指令的地址.每个逻辑地址都由一个端(segment)和偏移量(offset或displacement)组成,偏移量指明了从段开始的地方到实际地址之间的距离. 线性地址(Linear Address)(也称虚拟地址 Virtual Address):是一个32位无符号整数,可以用来表示高达4GB的地址.线性地址通常用十六进制数字来表示,值的范围从0x00000000到0xffffffff. 物理地址(

Linux内核剖析 之 内存管理

1. 内存管理区     为什么分成不同的内存管理区?     ISA总线的DMA处理器有严格的限制:只能对物理内存前16M寻址.     内核线性地址空间只有1G,CPU不能直接访问所有的物理内存.     ZONE_DMA                  小于16M内存页框     ZONE_NORMAL          16M~896M内存页框     ZONE_HIGHMEM        大于896M内存页框     ZONE_DMA和ZONE_NORMAL区域包含的页框,通过线性

Linux内核剖析 之 历史和体系结构分析

Linux 内核剖析 之 历史和体系结构分析       Linux 内核是一个庞大而复杂的操作系统的核心,不过尽管庞大,但是却采用子系统和分层的概念很好地进行了组织.在本文中,您将探索 Linux 内核的总体结构,并学习一些主要的子系统和核心接口.您还可以通过其他 IBM 文章的链接更深入地进行学习.       由于本文的目标是对 Linux 内核进行介绍并探索其体系结构和主要组件,因此首先回顾一下 Linux 的简短历史,然后从较高的层次审视 Linux 内核的体系结构,最后介绍它的主要子

Linux内核剖析 之 Linux源代码组成

Linux内核剖析 之 Linux源代码组成   ++++Linux:           ++COPYING:有关公共许可证制度GPL的具体说明.           ++README:Linux内核安装和使用的简要说明.           ++Makefile:重构Linux内核可执行代码的make文件.用来组织内核的各模块,记录了个模块间的联系和依托关系,编译时使用:仔细阅读各子目录下的Makefile文件对弄清各个文件这间的联系和依托关系很有帮助.           ++CREDIT

Linux内核中的内存管理浅谈

 [十月往昔]--Linux内核中的内存管理浅谈 为什么要叫做"十月往昔"呢?是为了纪念我的原博客. 不知道为什么,突然想来一个新的开始--而那个博客存活至今刚好十个月,也有十个月里的文档. 十月往昔,总有一些觉得珍贵的,所以搬迁到这里来. 而这篇文章是在09.04.20-09.04.21里写的. Jason Lee   ------------–cut-line   1.基本框架(此处主要谈页式内存管理) 4G是一个比较敏感的字眼,早些日子,大多数机器(或者说操作系统)支持的内存上限

为arm内核构建源码树----Linux内核剖析(四)

前面说到要做linux底层开发或者编写Linux的驱动,必须建立内核源码树,之前我们提到过在本机上构建源码树--Linux内核剖析(三),其建立的源码树是针对i686平台的,但是我么嵌入式系统用的是arm平台,这就需要我们为arm板交叉构建一份板子可用的内核源码树. 首先下载与你嵌入式系统平台版本号一致的linux内核,我的版本为2.6.35,当然如果你使用的是之前做好的板子,那么内核源码可能已经有了 我们解压缩我们的内核源码,并进入到内核源码的根目录 tar -jxvf linux-2.6.3

Linux内核中常见内存分配函数(二)

常用内存分配函数 __get_free_pages unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) __get_free_pages函数是最原始的内存分配方式,直接从伙伴系统中获取原始页框,返 回值为第一个页框的起始地址.__get_free_pages在实现上只是封装了alloc_pages函 数,Linux培训 从代码分析,alloc_pages函数会分配长度为1< kmem_cache_alloc str

Linux系统调用详解(实现机制分析)--linux内核剖析(六)

系统调用概述 计算机系统的各种硬件资源是有限的,在现代多任务操作系统上同时运行的多个进程都需要访问这些资源,为了更好的管理这些资源进程是不允许直接操作的,所有对这些资源的访问都必须有操作系统控制.也就是说操作系统是使用这些资源的唯一入口,而这个入口就是操作系统提供的系统调用(System Call).在linux中系统调用是用户空间访问内核的唯一手段,除异常和陷入外,他们是内核唯一的合法入口. 一般情况下应用程序通过应用编程接口API,而不是直接通过系统调用来编程.在Unix世界,最流行的API