Linux内核启动过程分析:从实模式到保护模式的关键步骤

Linux内核启动过程分析:从实模式到保护模式的关键步骤

linux-insides-zh Linux 内核揭秘 linux-insides-zh 项目地址: https://gitcode.com/gh_mirrors/li/linux-insides-zh

引言

在上一篇文章中,我们分析了Linux内核启动的初始阶段,了解了实模式下的基本设置过程。本文将深入探讨内核启动过程中从实模式切换到保护模式的关键步骤,这是操作系统能够充分利用现代CPU功能的重要转折点。

保护模式概述

保护模式是现代操作系统运行的基础模式,它提供了比实模式更强大的内存管理和硬件保护机制。理解保护模式对于深入掌握操作系统原理至关重要。

保护模式与实模式的主要区别

  1. 内存访问能力:实模式只能访问1MB内存空间,而保护模式可以访问4GB(32位)甚至更大的地址空间
  2. 内存保护机制:保护模式提供了内存段保护机制,防止应用程序随意访问内核空间
  3. 特权级别:保护模式引入了特权级概念(Ring 0-3),内核运行在最高特权级

全局描述符表(GDT)

保护模式的核心数据结构之一是全局描述符表(GDT),它定义了系统中所有内存段的属性。

段描述符结构详解

每个段描述符64位,包含以下关键信息:

63          48 47 46  44 43 40 39          32
------------------------------------------------
| Base 31:24 |G |D/B|L | 段限长19:16 |P |DPL|S| TYPE | Base 23:16 |
------------------------------------------------
31                            16 15            0
------------------------------------------------
|        Base 15:0            |      段限长15:0     |
------------------------------------------------

关键字段说明:

  • Base:32位段基址
  • Limit:20位段限长,决定段大小
  • G:粒度标志,0表示字节粒度,1表示4KB粒度
  • D/B:默认操作数大小/栈指针大小标志
  • L:64位代码段标志
  • P:段存在标志
  • DPL:描述符特权级(0-3)
  • S:描述符类型(0=系统段,1=代码/数据段)
  • TYPE:段类型属性

GDT的加载

内核使用lgdt指令加载GDT:

lgdt gdt_descriptor

其中gdt_descriptor包含:

  • 16位GDT大小
  • 32位GDT基地址

实模式到保护模式的切换流程

切换到保护模式需要严格按照以下步骤进行:

  1. 禁用中断:使用cli指令
  2. 加载GDT:使用lgdt指令
  3. 设置CR0寄存器:将PE位(第0位)置1
  4. 远跳转:清除指令流水线中的实模式代码
  5. 重新加载段寄存器:更新CS以外的段寄存器
  6. 建立保护模式栈:设置ESP和SS
  7. 启用中断:使用sti指令(可选)

内核启动过程中的关键初始化

控制台初始化

内核早期通过console_init()函数初始化控制台:

  1. 检查earlyprintk启动参数
  2. 根据参数配置串口
  3. 如果启用调试输出,显示初始化信息

putchar()函数实现细节:

  • 处理换行符转换(\n -> \r\n)
  • 通过BIOS中断显示字符
  • 如果串口初始化,同时输出到串口

堆初始化

init_heap()函数负责初始化早期堆:

  1. 检查CAN_USE_HEAP标志
  2. 计算堆栈结束地址
  3. 确定堆结束地址
  4. 调整堆栈位置避免冲突

CPU检测

validate_cpu()函数执行以下操作:

  1. 检查CPU级别是否满足最低要求
  2. 检测CPU特性标志
  3. 根据制造商设置特定选项
  4. 对于AMD CPU,检查SSE/SSE2支持

内存检测

detect_memory()函数使用多种方法检测内存:

  1. e820h接口:获取详细内存映射
  2. e801h接口:检测标准内存大小
  3. 88h接口:检测低端内存

e820h内存检测流程:

  1. 初始化调用参数
  2. 循环调用中断15h
  3. 收集内存区域信息
  4. 直到返回CF标志为止

键盘初始化

keyboard_init()函数:

  1. 获取键盘状态
  2. 设置按键重复率
  3. 存储键盘状态供后续使用

系统参数查询

内核查询多种系统参数:

  • 机器型号和BIOS版本
  • 高级电源管理(APM)信息
  • PCI总线配置
  • 显示适配器信息

总结

从实模式到保护模式的切换是Linux内核启动过程中的关键步骤。通过本文的分析,我们了解了保护模式的基本原理、GDT的结构与作用,以及内核在早期启动阶段进行的各种初始化工作。这些基础工作为后续内核的完整初始化奠定了基础,使操作系统能够充分利用现代CPU的特性,提供稳定可靠的运行环境。

在下一篇文章中,我们将继续分析内核启动过程,探讨如何进入长模式(64位模式)以及更高级的初始化步骤。

linux-insides-zh Linux 内核揭秘 linux-insides-zh 项目地址: https://gitcode.com/gh_mirrors/li/linux-insides-zh

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

戴艺音

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

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

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

打赏作者

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

抵扣说明:

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

余额充值