You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无OS环境下底层C(内核)分页设置与内存管理疑问

内核内存管理与分页机制疑问

背景说明

我基于os-series仓库修改了无操作系统的底层启动代码,目前能正常进入64位长模式并运行C编写的kernel_main,还实现了printf输出功能。启动步骤如下:

  • 在32位模式下通过esp寄存器设置栈
  • 检查multiboot、cpuid、long_mode可用性
  • 创建并初始化页表(仅直接映射内核前1GB物理内存到虚拟地址)
  • 创建并加载空GDT表
  • 进入64位/长模式
  • 清空ax、ss、ds、es、fs、gs等寄存器后调用kernel_main

分页启用后,所有代码都使用虚拟地址,且内核只能访问页表映射的前1GB内存,对剩余3GB内存的访问和管理存在以下疑问:

  1. 分页已启用时,如何访问虚拟地址空间中剩余的3GB内存?
  2. 内核是否通常使用不同页表,或者会在运行时禁用分页?
  3. 步骤3之后的所有汇编与C代码是否都使用虚拟地址?如果是,内核无需特殊技巧的话,该如何访问、管理剩余内存?
  4. 是否需要在内核运行时禁用分页?

核心解答

1. 访问剩余3GB内存的方法

分页启用后,要访问未映射的内存,最直接的方式是动态修改页表,将需要访问的物理内存区域映射到虚拟地址空间的空闲区域。比如可以在虚拟地址空间中预留一段区域(比如从0x40000000开始的3GB),当需要访问某段物理内存时,更新页表(修改PML4/PDPT/PD/PTE等页表项),将目标物理页映射到这段虚拟地址的空闲页上,之后通过对应的虚拟地址就能访问该物理内存。

注意修改页表后需要执行invlpg指令刷新TLB(Translation Lookaside Buffer),避免CPU使用旧的页表缓存。

2. 内核的页表使用策略

现代内核不会在运行时禁用分页,因为分页是内存保护、地址空间隔离、虚拟内存实现的基础。通常内核会使用一套独立的全局页表(所有进程共享内核部分的页表映射),而每个用户进程有自己的用户页表。不过在无完整进程管理的裸机内核阶段,只需要维护一套内核页表,动态扩展映射即可。

3. 步骤3之后的地址使用情况

是的,步骤3启用分页后,所有汇编和C代码的内存访问都会使用虚拟地址——CPU会自动将虚拟地址通过页表转换成物理地址。此时要管理剩余内存,不需要禁用分页,而是通过以下方式:

  • 先通过multiboot信息或BIOS/UEFI的内存探测功能,获取系统所有物理内存的布局(哪些区域可用、哪些是保留的)
  • 维护一个物理内存管理结构(比如空闲链表、位图),记录未被使用的物理页
  • 当需要使用某段物理内存时,从空闲结构中分配物理页,然后修改页表将其映射到虚拟地址空间的空闲区域,之后就能通过虚拟地址访问和操作这段内存

4. 是否需要禁用分页?

不需要。禁用分页会失去内存地址翻译带来的所有好处,而且在长模式下禁用分页的操作非常麻烦(需要切换回32位模式),完全没有必要。所有内存管理操作都可以在分页启用的状态下通过动态修改页表完成。


内容的提问来源于stack exchange,提问作者thxrben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:36:04