Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1027048
  • 博文数量: 136
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1800
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-21 22:26
个人简介

90后空巢老码农

文章分类

全部博文(136)

文章存档

2020年(34)

2019年(54)

2018年(47)

2017年(1)

我的朋友

分类: LINUX

2020-07-07 12:58:52

之前有一篇文章说过一次Linux当中的地址转换是通过MMU来实现的,今天来具体挖一挖这个过程

程序输出给cpu的是逻辑地址,经过cpu的硬件电路MMU当中的分段单元转为虚拟地址;虚拟地址再经过MMU当中的分页单元转换为物理地址

逻辑地址转换为虚拟地址
硬件当中的分段:
逻辑地址由段选择器和段内偏移量组成。每个段由一个8字节的段描述符表示,它描述了该段的一些特征(段的基地址等信息)。根据段选择器可以找到对应的段描述符,根据段内偏移量就可以得到虚拟地址。
根据段选择器查找段描述符的时候,可以去GDT或者LDT(两者用谁取决于段选择器当中的TI字段,并且这两者分别位于gdtr和ldtr两个寄存器当中)查找,而80x86为了加速,提供了6个8字节的非编成的寄存器,存储对应的6个可编程的段寄存器对应的段描述符。每当一个段选择符被装入段寄存器时,相应的段描述符就由内存装入到对应的非变成cpu寄存器当中了,这样,针对那个段的访问就不需要去主存中的gdt或者ldt拿数据,cpu只需要直接引用存放段描述符的cpu寄存器即可。仅当段寄存器的内容改变时,才有必要访问GDT或者LDT。

注意:由于一个段描述符是8字节长,因此它在GDT或者LDT内的相对地址是由段选择器的高13位乘8得到的,换句话说,段选择器的高13位就相当于是GDT或者LDT的索引。另外,GDT的第一项总是设置为0,这就确保空的段选择符的逻辑地址会被认为是无效的,进而引起一个处理器异常


linux当中的分段
运行在用户态的所有linux进程都使用一对相同的段来对指令和数据寻址——用户代码段和用户数据段。运行在内核态的所有linux进程都使用另一对相同的段对指令和数据寻址——内核代码段和内核数据段。相应的段选择器是由宏__USER_CS, __USER_DS, __KERNEL_CS, __KERNEL_DS分别定义。例如,为了对内核代码段进行寻址,内核只需要把__KERNEL_CS宏产生的值装进cs段寄存器即可。实际上,上述的4个段的base地址都是0,也就是说与段相关的线性地址是从0开始的,这也就意味着在用户态或者内核态下所有进程可以使用相同的逻辑地址,另一点就是逻辑地址等于现行地址。cpu的当前特权级CPL反映了进程是在用户态还是在内核台,这个东西可以通过cs寄存器当中存放的段选择器当中的DPL字段制定,只要当前特权级改变,一些段寄存器必须相应的更新。

Linux GDT
在单处理器系统中,只有一个GDT,而在多处理器系统中,每个cpu对应一个gdt。每个gdt包含18个段描述符和14个空的、未使用的项。插入未使用的项的目的是为了使经常一起访问的描述符能够处于同一个32字节的硬件高速缓存当中。18个段描述符指向下列段:
  • 用户态和内核态下的代码段和数据段共4个
  • 任务状态段(TSS),每个处理器有1个。每个TSS相应的线性地址空间都是内核数据段相应线性地址空间的一个子集。所有的人物状态段都顺序的存放在init_tss数组当中。第n个cpu的tss描述符的base字段指向init_tss数组的第n个元素
  • 1个缺省的局部描述符表的段。这个段通常是被所有进程共享的段,缺省的局部描述符表存放在default_ldt数组中,包含5个项
  • 3个局部线程存储(TLS)这种机制允许多线程的应用程序使用最多3个局部于线程的数据段。系统调用set_thread_area(), get_thread_area()分别用于创建和撤销一个TLS段
  • 与高级电源管理(AMP)相关的3个段
  • 与支持即插即用(PnP)功能的BIOS服务程序相关的5个段
  • 被内核用来处理双重错误(处理一个异常时引发了另一个异常)异常的特殊TSS段
虚拟地址转换物理地址:
硬件中的分页
分页单元把线性地址转换成物理地址,其中一个关键任务就是把所请求的访问类型与线性地址的访问权限相比较,如果这次访问是无效的,就会产生一个缺页异常。
把线性地址映射到物理地址的数据结构称为页表。页表存放在主存当中,并在启用分页单元之前必须由内核对页表进行适当的初始化。
常规的分页是两级,最高10位是页目录项,中间10位是页表项,最低12位是偏移量,前两项指定的均为物理页框地址,其中正在使用的页目录的物理地址存放在cr3寄存器当中,不同进程、用户态和内核台使用的页目录的物理地址不会一致。

页目录项和页表项由同样的结构,每项都包含如下字段:
  • present:1表示在主存中
  • field:包含页框物理地址最高20位的字段,低12位为0
  • accessed标志:每当分页单元对相应页框进行寻址时就会设置这个标志。当选中的页被交换出去时,这一标志就可以由操作系统使用
  • dirty标志:只应用于页表项中,每当对一个页框进行写操作的时候,就设置这个标志
  • read/write标志:含有页或页表的村区权限,0表只读
  • user/supervisor标志:含有访问页或页表所需的特权级。若为0,表示只有当CPL小于3时才能对页进行寻址;若为1,总能进行寻址
  • PCD和PWT标志:控制硬件高速缓存处理页或页表的方式
  • page size标志:只应用于页目录项,1表示目录项指向的是2MB或者4MB的页框(扩展分页)
  • global标志:只应用于页表项,用来防止常用页从TLB中刷新出去。只有在cr4寄存器的页全局启用标志(PGE)置位时才起作用

阅读(2559) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~