Linux在x86平台的启动过程

本文主要介绍Linux内核在32位x86机器上从上电后,一直到启动第一个进程init的过程。

一、首条指令

当用户按下电源键重启电脑的时候,CPU的默认取指地址被设置为0xFFFFFFF0,这个地址也是BIOS经映射之后所在的地址。然而,这个地址其实是超出实模式的地址范围的,即0 ~ 1MB。而x86上电的时候是运行在实模式下的,那么CPU又是如何执行到位于0xFFFFFFF0的指令的呢?原来,x86的段寄存器CS是由可见的段选择器和不可见的基地址两部分组成的。一般情况下,CPU运行在实模式时,指令的基地址由段寄存器CS左移4获得,但在CPU重启的时候,默认加载到段寄存器CS的值为0xF000,而基地址则加载了0xFFFF0000,EIP则是0xFFF0,于是指令的地址就变成了0xFFFF0000 + 0xFFF0 = 0xFFFFFFF0。

当CS在重启后被加载一个不同的值之后,运行在实模式的CPU就按一般的规则去生成指令的基地址,即:基地址 = CS * 16。

二、运行BIOS

一般情况下,BIOS在被映射到地址为0xFFFFFFF0的地方放置一条跳转指令,跳转到BIOS程序真正的入口地址开始执行。BIOS首先进行自检(POST),然后初始化硬件并根据启动配置搜索一个有效引导扇区(该扇区最后两个字节(魔数标识):0xAA55)。

BIOS搜索到启动扇区后,把该扇区(512字节)加载到地址为0x7C00的内存当中并跳转到该地址去继续执行。

三、运行Bootloader

一般来说,Bootloader会分成两部分,一部分就是刚被BIOS加载到0x7C00的预启动Bootloader程序,它先把自己挪到内存0x00096A00处,然后初始化实模式的堆栈,接着把Bootloader的第二部分通过BIOS提供的系统调用加载到内存地址为0x00096C00的地方,并从这里继续运行。

这时,Bootloader的第二部分借助BIOS提供的系统调用把内核的第一页数据(512字节)加载到内存0x00090000处,把setup()加载到0x00090200处,并把内核镜像的其他部分加载到0x00010000(小内核镜像)或者0x00100000(大内核镜像)。最后跳转至setup执行。

四、硬件初始化

Setup对电脑的硬件做一系列的初始化,包括鼠标、键盘、显卡、磁盘控制器等。接着,配置系统的中断描述符表(IDT)和全局描述符表(GDT)等系统环境。最后把处理器从实模式切换至保护模式,并跳转至startup_32()去执行。

五、初始化内核

Startup_32()函数先初始化了段寄存器、临时堆栈和BSS段,然后调用decompress_kernel()对内核镜像进行自解压,此时我们在串口中会看到“Uncompressing Linux...”。解压完后,CPU跳转至head.S的程序入口地址继续初始化内核的运行环境,包括重新配置段寄存器的最终数值,初始化内核堆栈,初始化GDT、IDT,使能Paging功能,启动进程0等,最后跳转至start_kernel()去执行。

六、启动内核

start_kernel()主要完成了以下工作:

  • 初始化调度器
  • 初始化内存区域及页表
  • 最后初始化中断列表IDT
  • 初始化softirq
  • 初始化系统时间
  • 初始化内存管理体系slab, slub, cache等
  • 创建init进程
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值