Linux内核剖析——操作系统的启动
一.总体功能
1.从通电到BIOS跳转
1.1 CPU在通电后,先进入实模式,设置CS=0XFFFF,IP = 0X0000(指向BIOS)
1.2 BIOS进行执行系统监测,并且在地址=0处初始化中断向量
1.3 将启动设备的第一个扇区(引导扇区,512B)读入0x7c00处
1.4 设置CS=0X07C0,IP=0X0000,跳转到该地址
2.BootSect.S
2.1 跳转到0x7c00时,该部分存放的是BootSect.S的程序,操作系统的所有故事从这开始
2.2 开始执行后,把自身移动到地址0x90000处,并把setup.S读入到0x90200处,内核其他部分被读入到0x10000处
机器从接电到开始的执行顺序如图
3.setup.S
3.1 进入setup.后,将会自动识别主机的某些特性和VGA卡类型,并可以要求用户选择显示模式。
3.2 将系统从0x10000处移动到0x0000处,进入保护模式并跳转到系统模块
4.head.S
设置并加载IDT,GDT,分页,CPU,并调用main.C中的main程序
5.Main.c
执行main程序
6.系统启动程序转移图
7.部分说明
7.1 bootsect.s为什么不直接移动内核程序位置,而要在setup.s中移动?
ans:
setup.s中的部分代码需要用到BIOS提供的中断向量表获取系统信息,在使用完BIOS之后才可将该区域覆盖。
- 2 仅在内存中加载了上述内核功能并不能让Linux系统运行,仍需要有完整的基本文件系统支持,即称为根文件系统。Linux0.12 使用了Minix的文件系统
二.BootSect.S 代码解析
主要作用
该程序的主要作用是把自己移动到0x90000处并执行,把第二个扇区开始的四个扇区的Setup.s模块加载到bootsect.s之后,使用0x13中断取用当前引导盘的参数,并显示Loading system字符串。随后确定根文件系统的设备号,保存于root_dev,最后跳转到setup处去执行setup.s程序。后缀是大写的S,可以使用GNU C的预处理功能。
核心代码
BOOTSECT = 0X07C0
INITSEG = 0X9000
SETUPSEG = 0X9020
mov ax,#BOOTSECT
mov ds,ax
mov ax,#INITSEG
mov es,ax
mov cx,256
sub si,si
sub di,di
rep
movw //将DS:SI的内容赋值道ES:DI中,即把自身移动到0x90000处
jmpi go,INITSEG//因为程序空间已经移动,所以需要使用jmpi指令进行继续执行
go:
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax//把段寄存器全部初始化为当前代码段
mov sp,0xff00//初始化栈
....//略过其余代码
load_setup://载入setup程序
xor dx,dx
mov cx,0x0002//扇区号为2
mov bx,0x0200
mov ax,0x0200+SETUPLEN//从第二个扇区开始,读4个扇区
int 0x13
//以上初始化0x13参数,并进行读取扇区,读入到es:bx
jnc ok_load_setup
xor dx,dx
xor cx,cx
int 0x13
j load_setup
ok_load_setup:
//..略去打印loading system部分
call read_it//读磁盘上的system模块
jmpi 0,setupseg//跳转到setup.s
//
三.Setup.S 代码解析
主要作用
利用BIOS中断读取机器系统数据,并将这些数据保存到0X90000的位置,覆盖掉BootSect.s的数据,这些参数将被内核中的相关程序使用
接着将system模块移动到0x0000处,加载idtr和gdtr,开启CPU保护模式,并跳转到最前面的head.S运行
为了能让head.S在保护模式中运行,本程序中临时设定了IDT和GDT,并在GDT中设置了当前内核代码段的描述符和数据段的描述符
核心代码
start:
mov ax,INITSEG
mov ds,ax//将DS设置为INITSEG
mov ah,0x03
xor bh,bh
int 0x10
mov [0],dx//通过中断取得光标位置
mov ah,0x88//获取扩展内存中断的功能调用
int 0x15
mov [2],ax//存储扩展内存数值
....//进行一系列参数获取
cli //不允许中断
mov ax,0x0000
cld
do_move:
mov es,ax//目的地址
add ax,0x1000
cmp ax,0x9000//是否已经移动玩
jz end_move//是,则跳转
mov ds,ax//源地址
sub di,di
sub si,si
mov cx,0x8000//移动64KB
rep
movsw
jmp do_move
call empty_8042//选通A20地址控制线,为了能使用1MB以上内存
mov al,0xd1
out 0x64,al
call empty_8042
mov al,0xdf
out 0x60,al
call empty_8042
mov ax,0x0001
mov cr0,ax//开启保护模式
jmpi 0,8//保护模式寻址,查询GDT进入0地址处
四.head.S 代码解析
notice:
head.s使用AT&T汇编编写,语法略有不同
主要作用
加载各个数据段寄存器,重新设置中断描述符表idt,重新设置GDT,检测A20地址线是否打开,设置分页后,打开main
核心代码
//主要就是调用main函数,过于简单,不写了
Linux内核剖析——操作系统的启动的更多相关文章
- 【转帖】Linux的历史----Linux内核剖析(一)
Linux的历史----Linux内核剖析(一) 2015年04月09日 10:51:09 JeanCheng 阅读数:11351更多 所属专栏: Linux内核剖析 版权声明:本文为博主原创文 ...
- [转帖]Linux内核剖析(一)Linux的历史
Linux内核剖析(一)Linux的历史 https://www.cnblogs.com/alantu2018/p/8991158.html Unix操作系统 Unix的由来 汤普逊和里奇最早是在贝尔 ...
- Linux内核剖析(四)为arm内核构建源码树
前面说到要做linux底层开发或者编写Linux的驱动,必须建立内核源码树,之前我们提到过在本机上构建源码树—-Linux内核剖析(三),其建立的源码树是针对i686平台的,但是我么嵌入式系统用的是a ...
- 通过gdb跟踪Linux内核装载和启动可执行程序过程
作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的:通过对一个简单的可执 ...
- linux内核剖析(零)linux系统启动过程详解-开机加电后发生了什么
本文参考了如下文章 深入理解linux启动过程 mbr (主引导记录(Master Boot Record)) 电脑从开机加电到操作系统main函数之前执行的过程 详解linux系统的启动过程及系统初 ...
- linux系统启动过程具体解释-开机加电后发生了什么 --linux内核剖析(零)
本文參考了例如以下文章 深入理解linux启动过程 mbr (主引导记录(Master Boot Record)) 电脑从开机加电到操作系统main函数之前执行的过程 详细解释linux系统的启动过程 ...
- Linux内核装载和启动一个可执行程序
“平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 理解编 ...
- linux内核剖析(六)Linux系统调用详解(实现机制分析)
本文介绍了系统调用的一些实现细节.首先分析了系统调用的意义,它们与库函数和应用程序接口(API)有怎样的关系.然后,我们考察了Linux内核如何实现系统调用,以及执行系统调用的连锁反应:陷入内核,传递 ...
- Linux内核剖析(五)Linux内核的构建过程
参考 一次实验引发的故事 – kernel build system探索—vmlinux是如何炼成的– kernel makefile 深度探索Linux操作系统:系统构建和原理解析.pdf 问题 在 ...
随机推荐
- centos8平台:redis6配置启用io多线程(redis6.0.1)
一,linux平台上redis6的安装 请参见这一篇: https://www.cnblogs.com/architectforest/p/12830056.html 说明:刘宏缔的架构森林是一个专注 ...
- mac 安装appium
mocOS 10.15.5 开启方式:设置->默认编辑器->Markdown编辑器
- Python函数名的应用和新特性格式化输出
1.函数名指向的是函数的内存地址. def func(): print(123) print(func,type(func)) # <function func at 0x000000000 ...
- 【C++】 C++异常捕捉和处理
在阅读别人开发的项目中,也许你会经常看到了多处使用异常的代码,也许你也很少遇见使用异常处理的代码.那在什么时候该使用异常,又在什么时候不该使用异常呢?在学习完异常基本概念和语法之后,后面会有讲解. ( ...
- WSL2和CUDA踩坑
WSL2和CUDA踩坑 WSL2里可以直接跑cuda了, 目前(2020年10月) 功能可用, 但bug很多, 不够完善 1. 安装 主要参考: https://docs.nvid ...
- filezilla pureftpd 读取目录列表失败
放行 21, 39000 - 40000端口
- 联赛模拟测试24 D. 你相信引力吗 单调栈
题目描述 分析 因为跨过最大值的区间一定是合法的,所以我们人为地把最大值放在最左边 我们要统计的就是在最大值右边单调不降的序列,可以用单调栈维护 需要特殊处理相同的情况 代码 #include< ...
- E. Almost Regular Bracket Sequence 解析(思維)
Codeforce 1095 E. Almost Regular Bracket Sequence 解析(思維) 今天我們來看看CF1095E 題目連結 題目 給你一個括號序列,求有幾個字元改括號方向 ...
- 利用python3监控服务器状态进行邮件报警
在正式的生产环境中,我们常常会需要监控服务器的状态,以保证公司整个业务的正常运转,常常我们会用到像nagios.zabbix这类工具进行实时监控,那么用python我们怎么进行监控呢?这里我们利用了p ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...