前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >VV的操作系统笔记(一)操作系统I SeeYou!!!!

VV的操作系统笔记(一)操作系统I SeeYou!!!!

作者头像
Pulsar-V
发布于 2019-04-17 07:57:49
发布于 2019-04-17 07:57:49
2K01
代码可运行
举报
文章被收录于专栏:Pulsar-VPulsar-V
运行总次数:1
代码可运行

注:与本系列博客同时同步的还有后面需要学习和研究的FreeRTOS和linux0.11-linux1.0内核代码VV的Linux操作系统内核笔记系列,即使笔者已经自己写了个操作系统了,但是为了能够使博客能读懂,笔者需要把每一个lab和代码打出来做出解释同时笔者也有自己繁重的学习和工作(本科狗),所以进度会非常非常慢

准备工作

Ubuntu16.04-i386 32位操作系统镜像

话不多说,迅雷下载下载地址

  1. 安装镜像到到虚拟机

安装过程不多赘述,安装完成如图所示:

  1. 安装ubuntu的一些软件和包
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apt-get install docker docker.io docker-compose qemu virtualbox 
  1. 安装IDE

Eclipse的CDT原生支持Makefile工程,而且虚拟机内存占用较小,所以这里我们就用Eclipse CDT注意是32位的Eclipse表问我为啥安装Eclipse Indigo这种老玩意,因为最新版本的EC并不支持32位。

在我们编写内核的过程中,我们使用GRUB来启动我们的内核。 至于为什么用GRUB,因为它可以设置多系统共存,这样的话你就可以打包多个系统内核同时存在并且启动的镜像文件。

操作系统启动流程

为了直观和形象,我们直接上图

  • BIOS(Basic Input/Output System),基本输入输出系统,该系统存储于主板的ROM芯片上,计算机在开机时,会最先读取该系统,然后会有一个加电自检过程,这个过程其实就是检查CPU和内存,计算机最基本的组成单元(控制器、运算器和存储器),还会检查其他硬件,若没有异常就开始加载BIOS程序到内存当中。详细的BIOS功能,这边就不说了,BIOS主要的一个功能就是存储了磁盘的启动顺序,BIOS会按照启动顺序去查找第一个磁盘头的MBR信息,并加载和执行MBR中的Bootloader程序,若第一个磁盘不存在MBR,则会继续查找第二个磁盘(PS:启动顺序可以在BIOS的界面中进行设置),一旦BootLoader程序被检测并加载内存中,BIOS就将控制权交接给了BootLoader程序。
  • MBR(Master Boot Record),主引导记录,MBR存储于磁盘的头部,大小为512bytes,其中,446bytes用于存储BootLoader程序,64bytes用于存储分区表信息,最后2bytes用于MBR的有效性检查。
  • GRUB(Grand Unified Bootloader),多系统启动程序,其执行过程可分为三个步骤:
    • Stage1:这个其实就是MBR,它的主要工作就是查找并加载第二段Bootloader程序(stage2),但系统在没启动时,MBR根本找不到文件系统,也就找不到stage2所存放的位置,因此,就有了stage1_5
    • Stage1_5:该步骤就是为了识别文件系统
    • Stage2:GRUB程序会根据/boot/grub/grub.conf文件查找Kernel的信息,然后开始加载Kernel程序,当Kernel程序被检测并在加载到内存中,GRUB就将控制权交接给了Kernel程序。

注意!现代操作系统使用了UEFI启动,但是我们现在不说UEFI,请自行忽略

但是这样也需要我们的Boot程序按照Mutileboot 规范来编译内核,才可以被GRUB引导。 按照Mutileboot规范,内核必须在起始的8KB中的(512字节)包含这一个多引导项头(Multiboot header)。 而且,这个多引导项头里面必须有3个4字节对齐的块。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
一个魔术块:包含了魔数[0x1BADB002],是多引导项头结构的定义值。
一个标志块:我们不关心这个块的内容,我们简单设定为0。
一个校检块:校检块,魔术块和标志块的数值的总和必须是0

我的内核启动代码如下: boot.s

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.set MAGIC, 0x1badb002;GRUB魔术块
.set FLAGS, (1<<0 | 1<<1);GRUB标志块
.set CHECKSUM, -(MAGIC + FLAGS);校验块

.section .multboot
	.long MAGIC
	.long FLAGS
	.long CHECKSUM
.section .text
.extern kernel_main;导入kernel_main
.extern system_constructors;导入系统构造函数
.global laoder

loader:
	mov $kernel_stack, %esp
	call system_constructors
	push %eax
	push %ebx
	call kernel_main

stop:
	cli
	hlt
	jmp stop

.section .bss
.space 2*1024*1024
kernel_stack:

一些code解释:

  • CLI:将IF置0,屏蔽掉“可屏蔽中断”,当可屏蔽中断到来时CPU不响应,继续执行原指令
  • STI:将IF置1,允许“可屏蔽中断”,中断到来转而处理中断
  • HLT:本指令是处理器“暂停”指令。
  • JMP:命令跳转指令
  • .global .global 用来让一个符号对链接器可见,可以供其他链接对象模块使用。 .global boot 让_start符号成为可见的标示符,这样链接器就知道跳转到程序中的什么地方并开始执行。linux寻找这个 bootbootbootstart标签作为程序的默认进入点。 在汇编和C混合编程中,汇编程序中要使用.global伪操作声明汇编程序为全局的函数,意即可被外部函数调用,同时C程序中要使用extern声明要调用的汇编语言程序。
  • .extern .extern XXXX 说明xxxx为外部函数,调用的时候可以遍访所有文件找到该函数并且使用它。
  • .long MAGIG .long指示声明变量占用空间,占32位
  • .set 给一个全局变量或局部变量赋值

现在建立符号链接来Link我们的所有object文件 linker.ld

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ENTRY(boot)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS {
	. = 0x0100000;
	.text :{
		*(.muiltboot)
		*(.text*)
		*(.rodata)
	}
	.data :
	{
		start_ctors = .;
		KEEP(*(.init_array ));
		KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
		end_ctors = .;
		
		*(.data)
	}
	.bss :
	{
		*(.bss)
	}
	/DISCARD/ : {
		*(.fini_array*) *(.comment)
	}
}

Makefile 没什么好说的,Makefile负责C/C++的 编译依赖过程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GCCPARAMS = -m32 -W -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPPARAMS = --32
LDPARAMS = -melf_i386
GCC = g++
ASM = as
LINKER = ld
CFLAGS = -o $@ -c $<
ASMFLAGS = -o $@ $<
LINKERFLAGS = -T $< -o $@ 

objects = boot.o kernel.o

%.o: %.c
	$(GCC) $(GCCPARAMS) $(CFLAGS)
	
%.o: %.s
	$(ASM) $(ASPPARAMS) $(ASMFLAGS)
	
kernel_lab.bin: linker.ld $(objects)
	$(LINKER) $(LINKERFLAGS) $(objects)
	
all: kernel_lab.bin
	echo "build successed"
clean: 
	rm -rf *.o
	rm -rf *.out
	rm -rf iso
	rm -rf *.iso
	rm -rf *.bin
	
rebuild: clean all
	echo "rebuild"
	
install: kernel_lab.bin
	sudo cp $< /boot/kernel_lab.bin

kernel_lab.iso: rebuild
	mkdir iso
	mkdir iso/boot
	mkdir iso/boot/grub
	cp kernel_lab.bin iso/boot/
	cp boot/grub.cfg iso/boot/grub/grub.cfg
	grub-mkrescue -o $@ iso
	rm -rf iso
	
kernel_vm: kernel_lab.iso
	(killall virtualbox) || true
	virtualbox -startvm "kernel_lab" &

下面是操作系统的主要程序,我们由C++编写,用extern "C"导出我们的函数符号 kernel.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "kernel.h"
//因为我们的操作系统没有TTY IO,所以我们需要重新写一个printf函数
extern "C" void  printf(char *str){
	u_short *monitor_io_memory=(u_short *)0xb8000;//注意!重点来啦!0xb8000内存地址是显示器地址,往这里写数据就直接能够输出到屏幕上
	for(int i=0;str[i]!='\0';++i){
		//写入字符串,取或0xff00的意思是我们需要把屏幕高四位拉低,否则就是黑色的字体,黑色的字体黑色的屏幕是啥也看不到的
		monitor_io_memory[i]=(monitor_io_memory[i] & 0xff00) | str[i];
	}
}
//操作系统构造函数委托方法
typedef void(*constructor)();
//全局定义构造委托
constructor start_ctors;
//全局定义析构委托
constructor end_ctors;

//轮询函数,并且执行
extern "C" void system_constructors(){
	for(constructor* i=&start_ctors;i!=&end_ctors;i+=1){
		(*i)();
	}
}
//操作系统主启动函数,这里我们打印一个字符串然后让操作系统进入等待
extern "C" void  kernel_main(const void *multiboot_structure,u_int magicnumber){
	printf("Hello Pulsar-V");
	while(1);
}

别忘了/boot/下的grub.cfg文件,这个是GRUB的配置文件,负责在启动器中列出我们需要启动的内核列表 grub.cfg

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
set timeout=10 #超时时间
set default=0 #默认启动项
menuentry "PulsarV's OS"	{
	multiboot /boot/kernel_lab.bin
	boot
}

现在,来看看我们的工程目录结构

在Ubuntu16.04的grub生成.iso镜像文件的时候如果出现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grub-mkrescue: warning: Your xorriso doesn't support `--grub2-boot-info'. Some features are disabled

的时候,就通过

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sudo apt-get install xorriso

来安装好你的xorriso 然后通过

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grub-mkrescue -o kernel_lab.iso iso

来打包我们的操作内核 接下来要做的事情就是控制台下输入编译命令先运行一下最基本的kernel

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
make kernel_vm

现在是show time! 首先看到的是我们的GRUB启动界面

接下来按下回车或者等待10s

大功告成,现在可以看见了我们的操作系统的Hello World了。

后记

如果启动失败了,就用压缩文件(Ubuntu归档管理器)的形式打开iso文件,检查你的目录结构和GRUB Config

参考文档: [Grub配置文件]http://www.jinbuguo.com/linux/grub.cfg.html [MIT公开课]https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall-2012/ [计算机操作系统第四版]

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux: 深入解析GRUB2引导加载器的核心原理
GRUB2(GRand Unified Bootloader 2)是现代计算机系统中广泛使用的引导加载器。它继承了GRUB的灵活性和强大功能,为用户提供了一个高度可配置和扩展的平台,用于引导多种操作系统。本文将深入探讨GRUB2的工作原理、配置方法以及常见应用场景,帮助读者更好地理解和使用GRUB2。
运维开发王义杰
2024/06/12
1.3K0
Linux: 深入解析GRUB2引导加载器的核心原理
《探秘计算机启动幕后英雄:BIOS/UEFI与GRUB/bootloader》
在我们日常使用计算机的过程中,按下电源键到操作系统界面出现,这看似瞬间的过程,背后却隐藏着一系列复杂且精妙的操作。其中,BIOS/UEFI与GRUB/bootloader扮演着举足轻重的角色,它们就像计算机启动流程中的幕后英雄,默默协作,确保系统顺利启动。今天,就让我们深入探寻它们的奥秘,揭开计算机启动的神秘面纱。
程序员阿伟
2025/04/26
1210
《探秘计算机启动幕后英雄:BIOS/UEFI与GRUB/bootloader》
CentOS7全自动安装光盘制作详解
系统安装的时候,按照ks.cfg文件的内容进行安装,我们把ks.cfg文件放到isolinux目录下:
力哥聊运维与云计算
2019/06/28
7.5K2
Linux系统自定义制作ISO安装镜像
在CentOS6系列版本系统在安装完成后会自动生成一个install.log文件,然后在CentOS7系列版本中就变化为anaconda-ks.cfg文件,它可以作为类似于Windows自动化安装的应答文件,只不过此处是用于Linux系统自动化安装的应答文件即无人值守自动化安装配置文件;
全栈工程师修炼指南
2022/09/29
11.7K0
【深度解析】Linux系统启动流程
Linux系统启动流程大概总结下来是这么一个过程: POST-->BootLoader(MBR)-->Kernel(硬件探测、加载驱动、挂载根文件系统、/sbin/init)-->init(/etc/inittab:设定默认级别、系统初始化脚本、启动及关闭对应级别的服务、启动终端) 详细分析上面的流程 第1步: 1.POST 打开电源按钮,CPU会把位于CMOS中的BIOS程序加载到内存里面执行,BIOS会探测并识别主板上的所有硬件,然后按照BIOS程序里面设定的启动顺序(1.光驱 2.硬盘 3.软驱 等)
小小科
2018/05/03
2.4K0
系统启动流程详解:从BIOS/UEFI到GRUB/Bootloader
这里推荐一篇实用的文章:《揭秘!Vue3.5响应式重构如何让内存占用减少56%》,作者:【前端欧阳】。
Echo_Wish
2024/11/19
2770
系统启动流程详解:从BIOS/UEFI到GRUB/Bootloader
写一个操作系统_03 引导内核
  接上一篇BIOS启动,BIOS完成了基础的硬件检测和硬件的中断向量表的初始化,然后BIOS找到MBR并且把MBR加载在内存中,跳转到该位置。加载的位置在内存中的0x7C00,至于为什么是这个位置,主要是因为历史的原因吧,最初的内存只有32K,历史选择了0x7C00(31k)。
changan
2020/11/04
1.1K0
GRUB多操作系统启动程序介绍与设置使用
描述:GRUB英文全称GRand Unified Bootloader俗称引导程序是硬盘中的软件,它可以启动用户在计算机中的多个操作系统所以也叫多重启动管理器。 目前主流版本是 GRUB2,在windows中也有类似的引导程序ntloader虽然它也可以引导Linux操作系统但是比较麻烦;
全栈工程师修炼指南
2022/09/29
8.6K0
GRUB多操作系统启动程序介绍与设置使用
Linux系统自定义制作ISO安装镜像
在CentOS6系列版本系统在安装完成后会自动生成一个install.log文件,然后在CentOS7系列版本中就变化为anaconda-ks.cfg文件,它可以作为类似于Windows自动化安装的应答文件,只不过此处是用于Linux系统自动化安装的应答文件即无人值守自动化安装配置文件;
全栈工程师修炼指南
2020/10/26
16.6K0
Linux启动流程与模块管理
系统的启动其实是一项非常复杂的过程,因为内核得要检测硬件并加载适当的驱动程序,接下来则必须要调用程序来准备好系统运行的环境,以让用户能够顺利的操作整台主机系统,如果你能够理解系统启动的原理,那么将有助于你在系统出问题时能够很快速的修复系统,而且还能够顺利的配置多重操作系统的多重启动问题,为了多重启动的问题,你就不能不学 grub 这个 Linux 下优秀的启动管理程序(boot loader),而在系统运行期间,你也得要学会管理内核模块,下面进入正题开始学习吧.
王 瑞
2022/12/28
1.4K0
从 1 到 0 构建博客项目(6) -- 操作系统篇(3)PXE 批量安装系统(EFI+BIOS)
官网地址:https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/installation_guide/chap-installation-server-setup
大大刺猬
2020/12/08
2K0
从 1 到 0 构建博客项目(6) -- 操作系统篇(3)PXE 批量安装系统(EFI+BIOS)
Linux启动流程 梳理| 思维导图 | 流程图 | 值得收藏
嵌入式与Linux那些事
2024/06/11
3850
Linux启动流程 梳理| 思维导图 | 流程图  | 值得收藏
操作系统的启动
操作系统的启动是个很令人好奇的话题,从按下计算机电源的那一刻,计算机从裸机开始呈现一个丰富的系统界面,这个从只有硬件逻辑到软件逻辑的过程是如何完成的?这里我们将从硬盘分区,三方协议,grub引导启动程序进行讲述,首先介绍硬盘MBR分区形式,然后介绍CPU,BIOS,系统的三方协议,讲述从CPU的硬件逻辑最终运行内核的软件逻辑的过程,最后介绍一下引导启动程序的发展,在grub这些引导启动程序中如何继续遵守三方协议。
hoikin-yiu
2020/08/25
1.4K0
操作系统的启动
Linux开机流程(中)
这小节将介绍各种BR(boot record)和各种boot loader,但只是简单介绍其基本作用。
陈不成i
2021/05/25
3.9K0
从无盘启动看 Linux 启动原理
作者:bobyzhang,腾讯 IEG 运营开发工程师 0. 故事的开始 0.1 为什么和做什么 最近家里买了对音响,我需要一个数字播放器。一凡研究后我看上了 volumio(https://volumio.org/) 这是一个基于 Debian 二次开发的 HIFI 播放器系统,可以运行下 x86 和树莓派上。 我打算让 volumio 运行在我 2009 年购买的老爷机笔记本上,也让它发挥一点余温热。正常操作是将 volumio 的系统镜像刷到 U 盘上,连接电脑后使用 U 盘启动系统即可。但是家
腾讯技术工程官方号
2020/11/02
8.9K0
Linux学习笔记之Linux启动引导过程
早期时,启动一台计算机意味着要给计算机喂一条包含引导程序的纸带,或者手工使用前端面板地址/数据/控制开关来加载引导程序。尽管目前的计算机已经装备了很多工具来简化引导过程,但是这一切并没有对整个过程进行必要的简化。
Jetpropelledsnake21
2019/02/15
10.8K1
linux centos系统开机启动流程
任何系统启动的第一步都是加电,也就是按下电源,然后计算机硬件会主动读取BIOS来加载硬件设备信息以及硬件设备的自我检测,之后系统会主动地读取第一个有引导程序的设备,该引导程序可以指定使用哪个内核来启动,并将其加载至内存当中运行,同时内核还要加载其他硬件设备以及对应的驱动程序,来使主机各个组件开始运行,等所有硬件设备加载完成之后,系统就真正启动来了,然后系统会操作一些外部程序开始准备软件的运行环境。之后加载一些系统运行所需要的软件程序。最后一步就是等待用户的登陆。
用户4877748
2020/07/22
3.6K0
【Linux】《how linux work》第五章 Linux内核的启动过程
You now know the physical and logical structure of a Linux system, what the kernel is, and how to work with processes. This chapter will teach you how the kernel starts— or boots. In other words, you’ll learn how the kernel moves into memory up to the point where the first user process starts.
阿东
2024/04/10
5630
【Linux】《how linux work》第五章 Linux内核的启动过程
tinycorelinux安装到硬盘_tty5
i.ttylinux 是一个基于2.6版内核、体积非常之小(5M左右的LiveCD)的Linux。它运行于i486以上平台的PC机上,安装之后,ttylinux的文件系统也只有8M大小,但却提供了一个完整的shell环境,并且可用来访问Internet;
全栈程序员站长
2022/09/21
1.3K0
Linux操作系统从BIOS到bootloader是如何运行的
操作系统一般都会在安装在硬盘上,在 BIOS 的界面上。你会看到一个启动盘的选项。启动盘有什么特点呢?它一般在第一个扇区,占 512 字节,而且以 0xAA55 结束。这是一个约定,当满足这个条件的时候,就说明这是一个启动盘,在 512 字节以内会启动相关的代码。
穿过生命散发芬芳
2025/02/04
2020
相关推荐
Linux: 深入解析GRUB2引导加载器的核心原理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验