尽可能选择C的方式去实现吧。
系统内核
系统上电后经引导程序引导后加载内核程序正式进入内核程序。进入内核程序首先进行一系列内核初始化工作。
低端内存
一般我们说的低端内存指的是0x00000~0xfffff这1M内存区间,x86在实模式下,或者早期的8086/8088,都只能访问到这1M内存区间。低端内存存放这很多重要的数据,当然在操作系统进入保护模式后,可能并不会使用到这些数据,也就不需要了。但在进入保护模式之前,比如还处于实模式下,系统还在引导阶段,没有这些数据是万万不行的。
可以确定的是,低端内存是主内存(RAM) 低于1M的那块内存区间。也不一定规定那1M完整的都是低端内存,有时候通常是低于640K的那块内存。我们可以通过两个BIOS中断可以知道低端内存的大小。
int 0x12
可以通过12H中断来获取低端内存的大小。
另一个还可以通过15H中断获取:
Int 15/AX=E820h
这个中断也可以获取低端内存的大小。
高端内存
高端内存就是除了地段内存这1M的内存区间外,高于1M的其余内存空间
系统内核可以加载到低端内存去执行吗?
内核加载到低端内存还是高端内存?
内核加载的位置
内核可以加载到低端内存或者高端内存
内核在什么时候加载?
最直接的方式就是在引导扇区的引导程序中去加载内核。这在内核程序比较小的时候是可以的,直接通过Int 13/AH=02h中断就可以把内核加载进来。
但是在这种情况下,如果内核程序是pe格式,如exe程序,或者elf格式,内核加载进来后还需要解析内核程序格式,设置各个段寄存器和偏移量,以便能够到正确的位置执行代码段指令和访问数据段数据和堆栈信息,这样的话,在引导扇区可能无法容纳这么多的代码了。
如果内核程序比较大了,现在在引导程序中是无法直接加载内核程序的。
在实模式下通过Int 13/AH=02h中断加载内核的时候,该中断有些限制,如“attempted DMA across 64K boundary or >80h sectors”,所以当内核程序比较大了,再加上内核加载的位置,很容易就碰到这种情况。如果使用其他中断或者其他方式加载内核的话,比如使用Int 13/AH=42h中断加载内核,这是个扩展中断,并不是所有的BIOS都支持该中断, 可能有些老的遗留BIOS并不支持扩展中断,目前看在Bochs下是支持该扩展中断,Bochs下的BIOS也支持该中断,但通过Int 13/AH=41h/BX=55AAh无法检查软盘是否支持扩展中断,Int 13/AH=41h/BX=55AAh在指定drive的时候只能指定硬盘的驱动器号:DL = drive (80h-FFh)。通过端口使用LBA或者CHS加载内核的话,只能通过硬盘加载,无法通过软盘进行加载。
内核加载方式
Int 13/AH=02h
Int 13/AH=42h
这是个扩展中断,可以通过Int 13/AH=41h/BX=55AAh检查BIOS是否支持扩展中断。
disk address packet
结构说明:
Format of disk address packet:
Offset Size Description (Table 00272)
00h BYTE size of packet (10h or 18h)
01h BYTE reserved (0)
02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)
04h DWORD -> transfer buffer
08h QWORD starting absolute block number
(for non-LBA devices, compute as
(Cylinder*NumHeads + SelectedHead) * SectorPerTrack +
SelectedSector - 1
10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer;
used if DWORD at 04h is FFFFh:FFFFh
其中:
04h DWORD -> transfer buffer
以及
10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer;
used if DWORD at 04h is FFFFh:FFFFh
指定的是物理地址。
结构定义:
// disk address packet // see Int 13/AH=42h for details. // // EDD also called Enhanced Disk Drive typedef struct { // size of packet. // // it must be 0x10 or 0x18. since struct disk_address_packet // is designed to be compatible with EDD-3.0, so the // size of struct is 24(0x18), the field p_edd_buffer // (64-bit flat address of transfer buffer for EDD-3.0) // is optional when the size of packet set to be 0x10. u1 p_size; u1 p_reserved; // reserved. u2 p_block_num; // transfer buffer // segment:offset u2 p_buffer_offset; u2 p_buffer_base; u8 p_start_block_number; // it's optional when the size of packet is 0x10, and it's needed when the size // of packet is 0x18. it's just for EDD-3.0 u8 p_edd_buffer; } disk_address_packet;
注意:p_buffer和p_edd_buffer指定的是物理地址。
#define DISK_ADDRESS_PACKET_SIZE 0x10 #define EDD_DISK_ADDRESS_PACKET_SIZE 0x18
相关函数声明:
// param 1: drive number // param 2: start block number and is a logic add- // ress. // param 3: the number of block to read // param 4,5: the data that read would write to the buff- // er. segment:offset // // Note: // the difference between logic address and physical a- // ddress is that logic address starting from 0 and ph- // ysical address starting from 1. int disk_read_0x42(u1 drive, u8 start_block_number, u2 num, u2 buffer_base, u2 buffer_offset); // for EDD-3.0 // // param 1: drive number // param 2: start block number and is a logic add- // ress. // param 3: the number of block to read // param 4: the data that read would write to the buff- // er. it's a physical address int edd_disk_read_0x42(u1 drive, u8 start_block_number, u2 num, u8 buffer);
disk_read_0x42
int disk_read_0x42(u1 drive, u8 start_block_number, u2 num, u2 buffer_base, u2 buffer_offset) { disk_address_packet packet = { .p_size = DISK_ADDRESS_PACKET_SIZE, .p_block_num = num, .p_buffer_base = buffer_base, .p_buffer_offset = buffer_offset, .p_start_block_number = start_block_number }; asm("push %ds"); asm("mov %ss, %ax"); asm("mov %ax, %ds"); asm("movw %0, %%esi" : : "p" (&packet)); asm("mov $0x42, %ah"); asm("mov %0, %%dl" : : "m" (drive)); __kint__(INT13); asm("pop %ds"); asm goto ("jc %l0" : : : : error); error: return 1; ok: return 0; }
00017955850i[BIOS ] int13_harddisk: function 00, error 07 !
通过端口方式
内核装载程序
为了加载内核,可以通过一个内核装载程序负责将内核程序加载并执行。引导程序只负责加载内核装载程序并执行。
内核程序可能是BIN,ELF,EXE,PE等格式,这里涉及到这些格式的内核程序的加载,BIN格式还比较简单,ELF,EXE,PE这些格式的加载比较复杂,关于这些格式的加载在其他章节中会涉及到。
关于os的一些整理:第二篇:5、内核EXE格式镜像:
关于os的一些整理:第二篇:4、内核PE格式镜像:
关于os的一些整理:第二篇:6、内核ELF格式镜像:
关于os的一些整理:第十篇:程序:
内核装载程序不大,引导程序可以很容易的将内核装载程序加载进来。
typedef struct { kl_image_format_t k_fmt; char *k_opt_hdata; char *k_data; u2 cs; u4 ip; u2 ds; u2 ss; u4 sp; } kl_image_t;
内核程序从什么时候开始执行?
引导程序通过一个远跳转到内核程序的入口地址开始执行。这里在编写的时候搞了个链接门的东西用于描述从一个地方跳转到另一个地方去执行。
在C程序中的描述大概也就是类似这样:
typedef struct { u2 offset; u2 segment; } link_gate_descriptor_t;
内核程序入口
系统启动执行一段时间后,执行到内核程序,调用内核程序入口函数进入内核执行。
入口函数
和c程序入口函数main类似,内核程序也应该有一个入口函数。
如:
void kmain(int argc, char** argv)
{
... ...
}
内核初始化
中断初始化
外设初始化
这里的外设初始化主要是对一些外设及相关控制器做一些基本的初始化设置。如显卡,键盘,鼠标等。
初始化显卡
设置显示模式
文本模式
图形模式
vga
初始化VGA
设置光标属性
开启显示光标
通常默认情况下,光标是启用的,如果是禁用状态,比如之前因为其他原因禁用了光标,应该开启显示光标。
显示内存设置
初始化键盘
检查键盘类型
检查扫描码集
设置键盘按键读取方式
初始化鼠标
设置鼠标读取方式
初始化控制台
初始化显卡
初始化键盘鼠标
初始化控制台输入缓冲
初始化磁盘
这里根据系统的引导方式选择对引导的磁盘做一些初始化操作。如通过硬盘引导,则对硬盘做一些初始化操作,如果是通过软盘引导,则对软盘做一些初始化操作。
初始化硬盘
初始化软盘
初始化网卡
初始化WIFI无线网卡
驱动初始化
IO初始化
初始化程序
初始化分区
对磁盘分区进行初始化。在引导程序中有一块区域用来存放磁盘分区信息。
结构
显示磁盘分区信息。
加载文件系统
加载各分区上的文件系统。
进程初始化调度
选择任务切换方式
启动第一个用户程序
内核程序格式
系统内核程序可以以exe形式(PE格式)、ELF格式或者二进制格式提供。
PE格式
ELF格式
二进制格式
内核程序以什么样的形式提供
系统内核程序可以事先按照指定格式烧录好在安装盘或者镜像程序中提供,或者以文件的形式提供。
相关推荐
"HCIA鸿蒙设备开发认证习题整理1" 本资源摘要信息对应的知识点主要涉及到HarmonyOS设备开发认证的相关知识领域,涵盖了操作系统、编程语言、开发工具、设备驱动、软件开发等方面。 一、操作系统 * HarmonyOS设备...
标题“OS_chapter1.rar”表明这是一份关于操作系统(Operating System, OS)的资料,章节为第一章。根据描述“笔记整理”,我们可以推测这可能是某位学习者或教师整理的操作系统基础理论的笔记,可能包括了概念解释...
在第二版中,你将会看到,你已经可以通过交叉编译的方式为我们的实验性 OS编写应用程序了,也就是说,它已经具备操作系统的基本功能,虽然仍然极其简陋,但第一个圈,毕竟是已经圆起来了。第三,实践类的操作系统...
本电子课件《操作系统原理教程(第二版)》由连卫民编写,旨在深入浅出地介绍操作系统的核心概念和技术。以下是根据课件内容整理的相关知识点: 1. 操作系统定义与功能: - 定义:操作系统是管理计算机硬件与软件...
`OSStart()`只能被调用一次,第二次调用将不会有任何效果。 #### 7. `void OSStatInit(void);` - **所属文件**: `OS_CORE.C` - **调用者**: 初始代码 - **开关量**: `OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN` - ...
在第二版中,你将会看到,你已经可以通过交叉编译的方式为我们的实验性 OS编写应用程序了,也就是说,它已经具备操作系统的基本功能,虽然仍然极其简陋,但第一个圈,毕竟是已经圆起来了。第三,实践类的操作系统...
这篇总结将围绕操作系统的核心知识点进行深入探讨,包括操作系统的基本概念、体系结构、进程管理、内存管理、文件系统、设备管理和调度算法等方面。 一、操作系统基本概念 操作系统(Operating System,简称OS)是...
在“高教类课件:操作系统原理与实训教程(第2版)”中,我们可以深入学习和理解操作系统的各项核心概念、设计原理以及实际应用。 一、操作系统概述 操作系统(Operating System,简称OS)是计算机系统的核心组成...
早期的图形用户界面如最初的Windows和Mac OS与操作系统内核紧密集成,虽然带来了快速的图形响应,但同时也意味着系统稳定性可能受到单一组件故障的影响。现在的操作系统,如Linux和改良版的Windows,采用了模块化...
**第2章 入门** 1. **终端与Shell**:学习如何使用命令行界面,熟悉Bash shell的基本操作,如命令行提示符、输入历史、路径导航等。 2. **基本命令**:教授ls、cd、mkdir、rm、cp、mv等常用文件管理命令,理解它们...
2. **.DS_Store**:这是Mac OS X系统中一个隐藏文件,存储了Finder关于文件夹的布局和设置信息。在压缩包中出现可能是用户在整理文件时产生的,通常对黑苹果系统工具的使用影响不大。 3. **dspci**:这是一个命令行...
在第一章的PPT中,可能还会详细讨论操作系统的发展历程,从早期的批处理系统、分时系统到现在的网络操作系统和分布式操作系统,以及操作系统的设计哲学,如单一任务、多任务、实时和嵌入式等。 此外,可能会涉及...
2. **计算机操作系统第三版 课后答案**: - 这可能是汤小丹等编著的《计算机操作系统》教材配套的习题解答,涵盖了进程、内存、文件、I/O、调度策略等章节的练习题解析,有助于深入理解概念和原理。 3. **琦 操作...
- 1:1模型: 一个操作系统进程对应一个线程。 - M:N模型: 多个操作系统进程对应多个线程,是最有效的模型但也是最复杂的。 - **运行模式**: - Kernel Mode (内核模式): 系统的核心部分运行在此模式下,拥有最高...
第二章:嵌入式硬件系统设计 在这一章中,你会深入学习嵌入式系统的硬件构成,包括处理器、存储器、输入输出设备等。重点在于理解不同类型的存储器(如ROM、RAM、Flash等)及其在系统中的作用,以及I/O接口的设计与...
Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的诊断和测试以及恢复系统功能的工具。小编的确一直都想把这方面的命令做个总结,这次辛苦老范给我们整理了这份实用的秘笈。 ...
历史上,诺基亚的一些经典型号如Nokia 6600、6630、N70和3250等均采用了Symbian OS。 【开发要求】 进行Symbian开发,首先需要注册成为Forum Nokia的会员,然后可以从官方网站下载SDK和开发环境。S60 3rd Edition ...