# linux0.11-project **Repository Path**: daofaren/linux0.11-project ## Basic Information - **Project Name**: linux0.11-project - **Description**: 从零编写linux0.11。从无到有逐步添加功能完善系统。 目前还没完成该项目。 - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 11 - **Created**: 2023-07-07 - **Last Updated**: 2023-07-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # linux0.11 project 这是一个从零编写linux0.11的工程。意在让学习操作系统的人看到一个操作系统是如何从无到有地构建起来的。 ## 背景 不少自制的操作系统代码复杂难懂,但linux0.11的代码相对简单清晰,而且有不少资料可以参考。通过它了解操作系统是个不错的选择。 于是我准备阅读linux0.11的代码,但还是会出现许多不理解的地方,比如文件系统的操作,可执行文件加载等。于是从零编写linux0.11的想法油然而生。我阅读过《30天自制操作系统》这本书,我认为一步步向操作系统中添加功能的想法很有意思,就向它学习,拆分操作系统,逐步完善功能。 每次添加功能的时候都让我纠结要加入哪个功能。尤其是进入main函数后,内存管理、任务管理、中断配置、文件系统都是有趣的内容。但每个内容都或多或少与其他内容有所联系,在拆分时令我头痛。 ## chapter目录 在主目录下有chapter_01、chapter_02等目录,代表第一章、第二章内容,每一章都有一个相应的任务。每一章下有几个小节,每一节完成任务的某一部分,每个小节都可以编译操作系统,在终端输入`make`指令回车即可运行。 自第九章起,运行操作系统还是执行`make`,调试需要打开两个终端,一个执行`make debug`,另一个执行`make gdb`。在后者输入并执行`c`就会跳转到 main 函数。 我稍微改动了原本的代码。比如把gas汇编改成Intel汇编,把a.out格式可执行文件改成elf可执行文件(a.out格式可执行文件的资料太少了),写一个简单的shell程序。所以它会跟原版linux0.11有点不一样。 为了能更好地讲解代码,发布博客,我也会改变没问题的代码,让它变得更容易讲解。魔改不会太严重。 最新的章节会不断删改,还请见谅。 ## libc目录 该目录下的代码用于编译可执行文件,可执行文件的格式是elf,使用静态库编译,生成的是与地址无关的指令。在该目录下`make`就会生成静态库和可执行文件。 ## blog目录 该目录存放了该工程的博客,是对代码的讲解。最好用typora阅读,并打开代码块的行号。 虽然写得不是太好,但还是将就着看吧。博客的讲解大量参考了《Linux内核完全注释》的内容,大部分的疑惑,相信都能在这本书中找到答案。 我也将博客发在了CSDN上,地址是:https://blog.csdn.net/mondaiji/category_11665249.html ## 工程目录 - 1.简单的bootloader - 1.1 简单的启动盘(先做个东西在bochs中跑起来) - 1.2 打印Hello World(向空白的启动盘中添加内容,看看界面的变化) - 1.3 boot和loader(加载setup.s并跳转到setup.s) - 1.4 完善setup.s(为跳转到保护模式做准备) - 2.内核初始化 - 2.1 添加内核(简单地加载简单的head.s) - 2.2 完善内核加载与移动(完整地加载head.s,复杂※) - 2.3 开始编写内核(在head.s重新设置idt、gdt,在main.c中定义用户栈) - 2.4 设置页表(在页目录中设置页表属性,在页表中设置页属性,跳转到main函数中) - 3.printk函数 - 3.1 获取机器系统参数(主要是屏幕信息,显存起始地址,大小等) - 3.2 屏幕初始化(用C语言变量保存上一节地信息,以供后面使用) - 3.3 简单的printk函数1(可格式化输出,不可处理非打印字符) - 3.4 简单的printk函数2(屏幕可滚动) - 3.5 简单的printk函数3(可处理非打印字符) - 4.部分系统初始化 - 4.1 内存初始化(设置空闲内存的起始和终止地址) - 4.2 缓冲初始化(初始化缓冲块结构体,用于文件系统) - 4.3 时钟初始化(获取系统当前时间,洛杉矶的,在进程管理时会用到) - 4.4 协处理器检查(检查x87协处理器是否存在) - 5.中断与异常 - 5.1 除零异常(除零异常是无错误码的异常) - 5.2 其他一些无错误码的异常(有上一节的内容所以代码很好写) - 5.3 双重故障(双重故障是有错误码的异常,顺便写了一些其它有错误码的异常) - 5.4 PIC初始化(初始化PIC,给外部中断先设置一个服务函数) - 6.进程管理 - 6.1 第一个任务(将当前运行的程序作为任务0) - 6.2 任务初始化与用户态(从核心态转到用户态) - 6.3 系统调用(实现一个简单的系统调用) - 6.4 fork - 分配页面 - 6.5 fork - 任务设置 - 6.6 fork - 复制页表 - 6.7 任务调度 - 6.8 页错误(写时复制) - 6.9 时钟中断 - 6.10 任务控制(任务睡眠、唤醒和结束) - 6.11 协处理器(添加与协处理器相关的终端和异常) - 6.12 信号 - 7.终端 - 7.1 数据结构介绍(tty_queue和tty_struct) - 7.2 键盘中断1(处理普通按键) - 7.3 键盘中断2(处理shift/ctrl/alt/cap/num) - 7.4 键盘中断3(处理func/cursor) - 7.5 完善终端(修改bug和丰富终端功能) - 8.软盘 - 8.1 软盘延迟(软盘开启或关闭电动机的延迟) - 8.2 软盘中断(开启并触发软盘中断) - 8.3 读取扇区(通过端口读取软盘扇区) - 8.4 查找扇区(规范化读取扇区的流程) - 8.5 申请需求(方便文件系统读取软盘数据) - 8.6 延时读写(修复之前代码的bug) - 8.7 处理结果(处理读写扇区时的出错问题) - 8.8 软盘选择(完善软盘处理) - 9.文件系统(一) - 9.1 qemu(将调试工具换为qemu) - 9.2 文件系统结构介绍 - 9.3 读取超级块 - 9.4 修改文件数据缓冲 - 9.5 获得根目录inode - 9.6 读取文件系统信息 - 9.7 open - 寻找文件所在目录 - 9.8 open - 读取文件信息 - 9.9 write - 字符设备文件 - 9.10 read - 读取普通文件 - 9.11 close - 关闭文件回收inode - 10.文件系统(二) - 10.1 write - 更改普通文件 - 10.2 sync - 同步软盘数据 - 10.3 creat - 创建普通文件 - 10.4 unlink - 删除文件 - 10.5 mkdir,rmdir - 增删目录 - 10.6 完善文件系统(修复前面代码的bug) - 11.可执行文件加载 - 11.1 elf可执行文件介绍 - 11.2 打印可执行文件信息 - 11.3 传递参数和环境变量 - 11.4 加载代码和数据 ## TODO - 根目录Makefile能自动找到文件 - Makefile增量编译 - 文件系统软盘换为硬盘 - 改用虚拟文件系统(vfs) ## Maintainer 就我一个人。。。毕竟linux0.11也是linus一个人写的,工作量不大。 ## License 我对这个不熟悉→_→,随便选一个,就选了GPL2.0。