内核页表学习记录

当做6.081 page tables实验时,看着其中的内核代码我产生了一些疑问,内核到底是使用物理地址还是逻辑地址?内核需要页表吗?内核页表的作用又是什么?

通过阅读书籍《深入理解linux内核》, 知乎得到了一些模糊的答案。

实模式与保护模式

从80286模型开始,Intel微处理器以两种不同的方式执行地址转换,这两种方式分别称为实模式和保护模式。
实模式存在的主要原因是要维持处理器与早期模型兼容,并让操作系统自举 ——P41 硬件中的分段

BIOS使用实模式的地址,因为在计算机加电启动时只有这些可以使用。一个实模式的地址由一个seg段和一个off偏移量组成。
相应的物理地址可以这样计算:seg*16 + off。所以CPU寻址电路根本就不需要全局段描述表,局部段描述表或者页表把逻辑地址转换成物理地址。显然,对全局段描述表,局部段描述表和页表进行初始化的代码必须在实模式下运行。——P826 附录一 系统启动-史前时代BIOS

80x86的三种地址(保护模式下)
逻辑地址:包含在机器语言指令中用来指定操作数或指令地址。逻辑地址由段基址和偏移量组成。
线性地址/虚拟地址:32位/64位无符号整数
物理地址:用于内存芯片级内存单元寻址,它们与从微处理器的地址引脚发送到内存总线上的电信号相对应。物理地址由32位/64位无符号整数表示
内存控制单元(MMU)通过一种称为分段单元的硬件电路把一个逻辑地址转换成线性地址,接着通过分页单元把线性地址转换成一个物理地址。 ——P41 内存地址

可以看出内核在刚启动时使用的是实模式地址(类似物理地址),而后在该模式下初始化段描述符,页表,再切换到保护模式,使用逻辑地址。
从80386开始,所有的80x86处理器都支持分页,它通过设置cr0寄存器的PG标志启用。当PG=0时,线性地址就被解释为物理地址

分段与分页

linux以非常有限的方式使用分段。实际上,分段和分页在某种程度上有些多余,因为它们都可以划分进程的物理地址空间:分段可以给一个进程分配不同的线性地址空间,而分页可以把同一个线性地址空间映射到不同的物理空间。与分段相比,linux更喜欢使用分页,因为:
1 当所有进程使用相同的的段寄存器值时,内存管理变得更加简单,也就是说它们能共享同样一组线性地址。
2 linux设计目标之一是可以把它移植到绝大多数流行的处理器平台上,然而,RISC体系结构对分段的支持很有限。

运行在用户态的linux进程都使用一对相同的段对指令和数据寻址,即用户代码段和用户数据段,相对应的,内核态的进程使用内核代码段和内核数据段,这些段的段基址均为0,这代表在linux下逻辑地址与线性地址是一致的,即逻辑地址的偏移量字段的值与相应的线性地址的值总是一致的。 ——P46 linux中的分段

linux中使用分段更像是一种兼容性措施,除了使用段描述符的一些字段外,没有啥用。

linux采用四级分页模型进行线性地址到逻辑地址的映射,这种级联的查询方式通过只为进程实际使用的虚拟内存区请求页表来减少内存使用量。
在这里插入图片描述
cr3寄存器存储页全局目录的物理地址,每一个进程有它自己的页全局目录和自己的页表集,进程切换时,cr3寄存器的值也需要换成下一个进程的页全局目录地址。

linux物理内存布局
在这里插入图片描述
进程线性空间分布
在这里插入图片描述
进程的线性地址空间分为两部分:(32位系统)

  • 从0x00000000到0xbfffffff(0-3G)的线性地址,无论进程运行在用户态还是内核态都可以寻址。
  • 从0xc0000000到0xffffffff(3G-4G)的线性地址,只有内核态的进程才能寻址。

内核页表建立

内核维持一组自己使用的页表,驻留在所谓的主内核页全局目录中。系统初始化后,这组页表还从未被任何进程或任何内核线程直接使用;更确切的说,主内核页全局目录的最高目录项部分作为参考模型,为系统中每个普通进程对应的页全局目录项提供参考模型。
在第八章将解释内核如何确保对主内核页全局目录的修改能传递到由进程实际使用的页全局目录中。
现在描述内核如何初始化自己的页表。这个过程分为两个阶段。事实上,内核映像刚刚装入内存,CPU仍然运行于实模式,所以分页功能没有被启用。
第一个阶段,内核创建一个有限的地址空间,包括内核的代码段和数据段,初始页表和用于存放动态数据结构的共128KB大小的空间。这个最小限度的地址空间仅能够将内核装入RAM和对其初始化的核心数据结构。
第二个阶段,内核充分利用剩余的RAM并适当建立分页表。 ——P74 内核页表

建立内核页表的步骤即为:通过简单的几条语句,建立临时的内核页表,开启分页功能,临时页表只映射当前需要用到的空间,例如对于32系统,假设需要映射8MB,页目录的每一项相当于4MB(页大小 * 页表大小),故只需映射两项。然后再建立最终的内核页表。

知乎回答:
1 Linux中内核页表是干嘛用的,为什么要有内核页表?
在这里插入图片描述
在这里插入图片描述内核中线性映射区对于物理内存的映射仅仅是建立映射,仅仅是为了内核可以直接访问这些内存,从而进行管理,而用户空间使用内存时建立的内存映射是基于内存分配的需求。

2 既然每个进程都拥有自己的页表,管理着该进程的内核空间和用户空间,那如果页表在内核空间中,访问页表不是会陷入内核?这样不会影响效率吗?但是看到许多地方都说到内核管理页表,而且内核页表和普通的页表到底有什么区别?
在这里插入图片描述

怎么理解linux内核栈?
关于linux内核栈,一直很困惑,找不到详细资料。

  1. linux内核栈是所有进程共享的吗,每个进程都有一个单独的内核栈?
  2. 从内核模块编程的角度看(不涉及用户态进程),内核栈该怎么理解?和用户进程进行系统调用使用的栈空间有什么不同?
  3. 怎么理解linux内核栈空间只有4KB或8KB,linux内核编程中的堆(heap)和栈(stack)有什么区别?

在这里插入图片描述
在这里插入图片描述

遗留问题:

  • 如何给用户分配内存
  • 内核页表的修改如何传递

参考博客:
Linux内核页表的建立
页表到底是保存在内核空间中还是用户空间中?
Linux中内核页表是干嘛用的,为什么要有内核页表?
linux内存子系统 - 建立内核页表
怎么理解linux内核栈?

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

最佳损友1020

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值