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 问题 在 ...
随机推荐
- postgresql 导出数据库与数据表
单表导出 pg_dump --host 127.0.0.1 --port 5432 --username "postgres" --role "postgres" ...
- APP打开(二)—标准流程
APP打开是一个老生常谈的话题,在互联网时代,在APP遍地的时代,APP打开是每一个APP的必经之路,今天我想通过以下几点来阐述APP打开的标准流程,给这个话题写一点自己的见解. APP打开现状 标准 ...
- echarts常用功能封装|抽象为mixin
目前已解锁以下功能: [x] 初始化echarts(initChart) [x] 获取echarts参数配置(getOption) [x] 生成echarts图表(setOption) [x] 监听r ...
- revel run报错 undefined: sys call.SIGUSR2"
revel run报错,报错信息为 o Compilation Error (in ..\\..\\revel\\server_adapter_go.go:135): undefined: sysca ...
- C# 中的只读结构体(readonly struct)
翻译自 John Demetriou 2018年4月8日 的文章 <C# 7.2 – Let's Talk About Readonly Structs>[1] 在本文中,我们来聊一聊从 ...
- 第 1 篇:Vue.js 很高兴认识你
作者:HelloGitHub--追梦人物 Hello Vue 既然是学习编程,那就遵循一下那个古老的传统仪式. 首先我们新建一个 todos.html 文件,用任何一个你喜欢的文本编辑器或者 IDE ...
- Redis 数据结构与编码技术 (Object Encoding)
数据结构实现 相信大家对 redis 的数据结构都比较熟悉: string:字符串(可以表示字符串.整数.位图) list:列表(可以表示线性表.栈.双端队列.阻塞队列) hash:哈希表 set:集 ...
- 记一次微信公众号(微信H5)网页对接腾讯云慧眼人脸核验开发笔记
需求是这样的,客户需要一个在观看学习视频前弹出人脸识别核验真人的功能,客户找了个APP作为参考,但是在微信上第三方人脸识别是无法直接调取到前置摄像头的,都是通过用户自己获取用户的身份信息或者照片,然后 ...
- 深入研究Paxos算法原理
一.Paxos算法产生的背景 Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一,其解决的问题就是在分布式系统中如何就某个值(决议)达成一致. ...
- 令人惊叹的百度Echarts,大数据分析的必备工具
学习目录 1.可视化面板介绍 1.1技术要点 1.2案例适配方案 1.3页面主体布局2.Echarts(重点) 2.1echarts介绍 2.2echarts体 ...

