首页 Home.
-
自制操作系统(10):内核堆分配器 在上一节,我们成功地实现了虚拟内存管理器,并把显存的映射进行了重新调整,但是现在我们能申请的内存粒度过大,如果有这么一种经常出现情况:我们只需要申请若干个字节的内存,余下的内存就是一种浪费,造成过多的内部碎片。因此我们需要为内核开发实现一个粒度更小的可用空间管理器,也就是内核堆分配器。有了这样的分配器,我们就能像使用用户态的malloc和free一样,用kmalloc和free申请堆内存了。 接口 老规矩,我们先通过外部的接口来判断它能为我们带来什么。 void kheap_init(); void* kmalloc(uint32_t size); void […]
2026年3月1日 60 次浏览 -
自制操作系统(9):虚拟内存管理 在上一节,咱们实现了用Multiboot协议拿到空闲物理内存的分布,以及用自己实现的物理内存管理器(PMM)对这些空闲内存进行管理。但是现在还有一个问题,我们从PMM拿到的都是物理内存地址,而我们已经开启了分页机制,这使我们面临两个问题: 1、不是所有的空闲内存物理地址,都有对应的页映射。也就是很大一部分物理内存,是没办法通过虚拟地址访问的。 2、即使是那些有对应页映射的物理内存,我们也没办法直接访问,需要将物理内存地址映射到虚拟地址才能使用这些空闲内存,目前我们是采用硬编码的方式(+0xC0000000); 那么接下来,我们要实现的虚拟内存管理,就能解决这两 […]
2026年2月26日 39 次浏览 -
自制操作系统(8):物理内存管理 上一节,我们开启了时钟中断并实现了sleep函数,最重要的是:我们把之前留下来的一个坑——高半区内核,给填上了。但是因为我们过于“硬核”的显存区域映射方式,我们又留下了一个新的坑,不过不用担心,我们接下来将要实现的内存管理,就是可以把这个坑填上的一个特性。 接下来,我们开始涉足内存管理的领域,来谈谈怎么样管理物理内存。 为什么要进行内存管理呢?说白了,我们现在的内存不像以前那样寸土寸金,但是也不是用之不竭的,最好就是无论是内核还是用户进程,需要用到内存的时候,我们能够在内存里面找到一块空闲的地方,然后分配给它;声明用不到的话,我们又能回收掉这段内存,以备不时之 […]
2026年2月23日 42 次浏览 -
自制操作系统(7):定时中断与sleep(),迁移内核到高半区 在上一节,我们成功地接管了键盘的中断,并重构了一些代码,实现键盘驱动,并实现了一个玩具Shell,今天我们要搞点硬核的东西,但是在此之前,我们先来点轻松的——实现一个sleep函数。 PIT(可编程间隔定时器) PIT接收一个保持一定频率(1,193,182 Hz)的振荡器产生的输入信号,然后根据通过栅极输入(Gate Input)编程的配置,在不同的频道产生不同的栅极输出。PIT与键盘一样也是一种硬件,都可以通过IO端口与CPU进行数据互通。因此,我们可以通过IO端口对其进行编程。 PIT逻辑上有三个频道,0号频道连向了PIC芯 […]
2026年2月21日 38 次浏览 -
自制操作系统(6):硬件中断与键盘驱动 上一篇文章我们设置了GDT与IDT,现在,我们的系统能处理软件中断了。今天,我们来让我们的操作系统具备处理硬件中断的能力。 硬件中断 硬件中断相对于软件中断,顾名思义就是由硬件向CPU发出的中断了,比如说键盘输入、硬盘读取等等,都会向CPU发送中断来告知硬件目前所处的状态以及新发生的一些事件。 但是硬件其实并不直接向CPU发送中断,它们俩的桥梁是一个叫8259 PIC(可编程中断控制器) 的芯片。 硬件中断重映射 由于一些早年的不兼容的设计,8259会有默认的,从IRQ到IDT的如下的映射: 主片 (Master PIC):负责 IRQ 0-7。在 IB […]
2026年2月18日 34 次浏览 -
自制操作系统(5):GDT与IDT 在上一篇文章,我们完善了控制台逻辑,拥有了一套比较可用的控制台输出函数,这为我们后续的调试提供了基础。 现在,我们来稍微给kernel_main加一句代码,来测试一下会发生什么: printf("1 / 0 = %d\n", 1 / 0); 可以看到,我们的系统居然被这个小小的除0打败了,正在不断的重启,没有办法进入系统了! 这很荒谬,但是究其原因,是我们没有正确地设置中断描述符表(IDT),今天我们就来围绕IDT,还有相关的GDT来完善我们的操作系统。 GDT(全局描述符表) 要设置IDT,我们最好先设置好自己的GDT; 而聊到GDT, […]
2026年2月15日 32 次浏览 -
自制操作系统(4):libc完善——控制台逻辑完善更多的输出字体 在上一篇文章我们重构了kernel,创造了一个简陋的libc,并成功地把二者链接了起来。 下面我们来完善这个libc,首先从一些“所见即所得”的东西入手,今天最终的目标是用这个libc来输出一个露米娅的AA(ASCII ART)。 字体完善-从8*8到8*16 现在8*8的字体有点不够带劲,而且只支持几个简单的字体,我们让AI生成一个更大更完善的字体库,并稍微修改一下我们的终端输出逻辑,具体是,我们检测到当前要输出的是换行符的话,我们重置字符输出的列,并将输出的行+1.(你说这应该是\r\n而不是\n?我觉得像Unix那样简单点 […]
2026年2月13日 32 次浏览 -
自制操作系统(3):从Bare bone到Meaty skeleton(下) 在上一节,我们重新组织了文件架构,重构了一些代码,并引入了makefile来辅助构建,我们可以用更干净的架构去输出我们的Hello world了。 extern "C" void kernel_main(multiboot_info_t* mbi) { // 1. 初始化硬件 terminal_initialize(mbi); // 2. 定义颜色 uint32_t white = 0x00FFFFFF; uint32_t green = 0x0000FF00; // 3. 业务逻辑:打印字符 / […]
2026年2月11日 29 次浏览 -
自制操作系统(2):从Bare bone到Meaty skeleton(上) 在上一节,我们利用GRUB来实现了引导程序,并成功在屏幕上输出了Hello world。 虽然代码是用AI写的,但是我们已经把比较繁琐的编译环境配置这项搞定了!~可喜可贺。 可是瞅一眼我们的配置目录,我们会发现这里面堆放的文件很杂乱。 我们应该用某种规则来重新组织下我们的文件,虽然现在的文件不多,但是随着我们逐步完善操作系统,文件数量肯定会越来越多,因此我们要提前做好规划。我们不妨用下面的方式来组织我们的文件: 目标结构:Meaty Skeleton 的“四大支柱” 我们要将项目拆分为四个核心逻辑区域。这种结构模仿了 […]
2026年2月9日 36 次浏览 -
自制操作系统(1):内核Hello world 注:这篇文章并不完整,因为我一开始没打算记录制作的全过程,所以一开始并没有写这一章...后面会把它补充完整,请见谅。 全程参考:https://osdev.wiki/wiki/Multiboot1_Bare_Bones。 毫不避讳地说,Bare bone这里AI帮我写了绝大部分的代码,因为:1、这部分代码不多,而且绝大部分在后面会被替代;2、我没有进行过内核编程,我不想太过苛求自己,让自己一开始就困在各种报错和调试中,为自己带来太多的挫败感;3、我想先让自己能尽快“看到点什么”——反馈是很重要的! 开发环境 WSL2+VSCode 准备工作:交叉 […]
2026年2月7日 31 次浏览
