前言

最近接了一个外包项目再加上填一些之前立的flag,发现好像很久没有发博客了。现在编译原理操作系统算法方面都还有大坑没有填,加上离实习越来越近,应用层方面的学习也要加强了,但反倒是压力越大越想摸鱼

之前暑假的时候跟着书上写过一个玩具操作系统,然后之后还翻了一下Linux0.11一起写了一个系列的博客,但是还是觉得认识的太浅薄,然后最近发现清华大学的一个操作系统课程,就跟着了。准备用博客来记录一下,虽然会和之前的那个系列有些重复,但是也算是加强巩固了

BIOS

对于所有寄存器开机时都有各自的初始值,在X86中,CS和EIP寄存器分别是F000H,0000FFF0H,所以X86开机执行的第一条指令就是位于这个位置的指令,一般这条指令都是长跳转指令,从这里跳到BIOS程序的起始位置。

BIOS的工作是硬件自检和初始化,并且读取该设备的第一扇区,并且转交CPU控制权

bootloader

由BIOS加载的第一扇区一般放的都是bootloader,bootloader的工作就是

  • 切换到保护模式,启用分段机制
  • 读取磁盘中的操作系统内核
  • 将CPU控制权转交到操作系统

实模式

实模式的存在主要是为了兼容老的操作系统(16bit),在这种状态下软件可访问的物理内存空间不能超过1MB,主要的区别就是实模式的寻址能力和方式,实模式将整个物理内存看成分段的区域,程序代码和数据位于不同区域,操作系统和用户程序并没有区别对待,而且每一个指针都是指向实际的物理地址。

段基址 << 4 + 段内偏移

所以对于32位的处理器就有了保护模式。bootloader的一个工作就是将实模式切换为保护模式

保护模式

在保护模式下,对内存的管理就采用了分段机制,当然在后面还会有分页机制

分段机制将内存划分成以起始地址和长度限制这两个二维参数表示的内存块,这些内存块就称之为段

段机制里会有四个概念:

  • 段选择子

在实模式下,段寄存器原本存放的是段基址,但在保护模式下存放的是段选择子,段选择子的本质其实是一个索引,在全局描述符表的索引,但是它还包含其它信息,比如特权级信息

  • 全局描述符表

全局描述符表,其实就是一个保存着段描述符的数组

  • 段描述符

至于段描述符就是真正描述物理地址的数据结构了,每个段由如下三个参数进行定义:段基地址(Base Address)、段界限(Limit)和段属性(Attributes)。段属性里包含了一个特权级信息等等

  • 特权级

至于保护模式为什么叫做保护模式,可能就是因为它指定了代码都是在一个特定的特权级下运行的,从而决定了代码可以做什么,不可以做什么

  1. CPL:当前特权级(Current Privilege Level) 保存在CS段寄存器(选择子)的最低两位,CPL就是当前活动代码段的特权级,并且它定义了当前所执行程序的特权级别)
  2. DPL:描述符特权(Descriptor Privilege Level) 存储在段描述符中的权限位,用于描述对应段所属的特权等级,也就是段本身能被访问的真正特权级。
  • 地址转换

在没有进入到保护模式的时候,对应的地址就是相应的物理地址,但是在启动了保护模式下,逻辑地址--> (分段地址转换) -->线性地址 == 物理地址

bootloader主要代码

void
bootmain(void) {
// 读取第一扇区
readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0); // 判断操作系统内核编译后的文件是不是有效的ELF文件
if (ELFHDR->e_magic != ELF_MAGIC) {
goto bad;
} struct proghdr *ph, *eph; // 加载内核
ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff);
eph = ph + ELFHDR->e_phnum;
for (; ph < eph; ph ++) {
readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset);
} // 启动内核
((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))(); bad:
outw(0x8A00, 0x8A00);
outw(0x8A00, 0x8E00); /* do nothing */
while (1);
}

中断和异常

操作系统和CPU一起提供了一种能够打断操作系统和应用的正常执行,让操作系统完成相关处理,然后在恢复操作系统和应用的正常执行。在操作系统中,这种机制称为中断机制。

当CPU收到中断(通过8259A完成)或者异常的事件时,它会暂停执行当前的程序或任务,通过一定的机制跳转到负责处理这个信号的相关处理例程中,在完成对这个事件的处理后再跳回到刚才被打断的程序或任务中。

中断向量和中断服务例程的对应关系主要是由IDT(中断描述符表)负责。操作系统在IDT中设置好各种中断向量对应的中断描述符,留待CPU在产生中断后查询对应中断服务例程的起始地址。而IDT本身的起始地址保存在idtr寄存器中。

IDT的代码实现

void
idt_init(void) {
// __vectors中存放的就是所有的中断处理程序
extern uintptr_t __vectors[];
int i;
for (i = 0; i < sizeof(idt) / sizeof(struct gatedesc); i ++) {
// 设置中断门
SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL);
}
// 加载进寄存器中
lidt(&idt_pd);
}

所有的中断处理程序最后都是进行一些寄存器的保存然后最后交由__alltraps调用trap

.globl vector0
vector0:
pushl $0
pushl $0
jmp __alltraps
.globl vector1
vector1:
pushl $0
pushl $1
jmp __alltraps __alltraps:
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushal movl $GD_KDATA, %eax
movw %ax, %ds
movw %ax, %es pushl %esp call trap popl %esp .globl __trapret
__trapret:
popal popl %gs
popl %fs
popl %es
popl %ds addl $0x8, %esp
iret

最后trap调用trap_dispatch根据不同的服务来执行相关代码

void
trap(struct trapframe *tf) {
trap_dispatch(tf);
}

Lab1:bootloader操作系统的启动的更多相关文章

  1. 我是如何学习写一个操作系统(二):操作系统的启动之Bootloader

    前言 今天本来的任务看书和把之前写的FragileOS整理一下,但是到现在还在摸鱼,书也只看一点.后来整理了一下写这个系列的思路,原本的目的是对操作系统原理性的学习和对之前写的一个玩具型操作系统的回顾 ...

  2. 通过从代码层面分析Linux内核启动来探知操作系统的启动过程

    通过从代码层面分析Linux内核启动来探知操作系统的启动过程 前言说明 本篇为网易云课堂Linux内核分析课程的第三周作业,我将围绕Linux 3.18的内核中的start_kernel到init进程 ...

  3. ucore lab1 bootloader学习笔记

    ---恢复内容开始--- 开机流程回忆 以Intel 80386为例,计算机加电后,CPU从物理地址0xFFFFFFF0(由初始化的CS:EIP确定,此时CS和IP的值分别是0xF000和0xFFF0 ...

  4. 操作系统的启动与引导问题 BIOS、UEFI、MBR、GPT

    关于ISO.WIM.GHO三者的正确理解. ISO(Isolation)文件一般以ISO为扩展名,是复制光盘上全部信息而形成的镜像文件. WIM是英文Microsoft Windows Imaging ...

  5. Linux内核剖析——操作系统的启动

    一.总体功能 1.从通电到BIOS跳转 1.1 CPU在通电后,先进入实模式,设置CS=0XFFFF,IP = 0X0000(指向BIOS) 1.2 BIOS进行执行系统监测,并且在地址=0处初始化中 ...

  6. 通过简单的Linux内核启动程序代码窥探操作系统的启动原理

    作者:吴乐  山东师范大学 <Linux内核分析> 孟宁 MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.程序设计与分析 ...

  7. CC3200模块的内存地址划分和bootloader,启动流程(二)

    1. 首先启动内部ROM固化的BOOT,然后这个ROM启动需要使用内存空间0X2000 0000 --- 0X2000 4000共16K的空间.一级BOOT的作用是串口升级和驱动库. 2. 然后是二级 ...

  8. 制作安装Linux操作系统的启动U盘方法其实就这么简单

    安装系统前,我们需要制作系统安装启动U盘(或者DVD,但已经很少使用DVD,所以不再介绍),通过启动U盘来帮助我们安装下载好的Linux系统. 接下来我们来介绍在Windows.Linux和MacOS ...

  9. Linux基础:操作系统的启动

    Centos6: # 1.加电自检(BIOS)# 2.MBR引导(512k)dd </dev/zero >/dev/sda bs=1k count=400 # 3.GRUB菜单(选择系统) ...

随机推荐

  1. excel中统计COUNTIFS的值为0

    excel中统计COUNTIFS的值为0 个人认为是由于导出的文件里面的字符个数问题 使用 =COUNTIFS(H1:H175,"微信支付") 这个的结果居然是0,找了很多办法 于 ...

  2. C# 通过反射获取winform上的控件

    比如获取Button按钮: System.Reflection.FieldInfo[] fieldInfo = form.GetType().GetFields(System.Reflection.B ...

  3. linux中上传文件出现Refused to display 'http://***' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

    刚开始出现这个问题,去百度了一下,网上很多答案都是一致的,但是在我这里没有解决问题.这个问题服务器没有打印日志.说明没有访问到服务器上,但是前端又没有问题,很奇怪,后面终于有一个同事和我说会不会是腾讯 ...

  4. P2995 [USACO10NOV]牛的照片(树状数组,逆序对)

    题目: P2995 [USACO10NOV]牛的照片Cow Photographs P4545 [USACO10NOV]奶牛的图片Cow Photographs SP7809 COWPIC - Cow ...

  5. ELK——Elasticsearch 搭建集群经验

    本文内容 背景 ES集群中第一个master节点 ES slave节点 迁移到:http://www.bdata-cap.com/newsinfo/1712679.html 本文总结 Elastics ...

  6. sqlserver 远程链接

    远程链接的文档就不说了,网上好多. 这里就说下我遇到的情况,如果是阿里云的服务器的话,他的端口配置都是要到阿里云里的安全组里去配置的,第一次一直没想到,搞了一天才发现,在这里提醒各位好友.

  7. web安全常用工具

    简单工具:明小子,阿d注入工具,namp,穿山甲,御剑,旁注 漏洞扫描工具:appscan .awvs.nbsi 端口扫描工具:nessus.namp.天镜脆弱性扫描与管理系统 数据库备份工具:中国菜 ...

  8. H5离线缓存(基础)学习指南

    离线缓存 application cache 1. 什么是离线缓存: 离线缓存可以将站点的一些文件缓存到本地,它是浏览器自己的一种机制,将需要的文件缓存下来,以便后期即使没有连接网络,被缓存的页面也可 ...

  9. NI CWGraph 显示波形图

    ptrWaveBox.Axes(1).Maximum = 1000 ptrWaveBox.Axes(2).Maximum = 20 ptrWaveBox.Axes(2).Minimum = 0 Dim ...

  10. HTML5-表单 自带验证

    表单语法<form method="post"(规定如何发送表单数据 常用值:get|post) action="result.html">(表示向 ...