【Create my OS】从零编写一个操作系统

前言

相信每个自学操作系统的同学,大致学习路线都离不开 HIT-OS、MIT-6.S081、MIT-6.824、MIT-6.828等经典的公开课。但学习完这些经典公开课并完成相应的Lab,很多同学脑海中对于操作系统的知识其实都是零散的,让你从头开始编写一个操作系统,我相信大部分人还是无从下手。因为Lab只是修改相应的核心模块,对于整体系统的组织、模块间的处理等细节,往往没有人去关注,也就是说我们还需要进一步把这些概念串起来、巩固起来。那么,我相信大部分人都有过一个想法:"我能不能自己写一个操作系统",这可能是大部分操作系统开发人员的梦想吧。
因此!本项目将展示如何从零开始使用 ANSI C 编写出一个基于 64 位 RISC-V 架构的操作系统------Jokerix,该系统支持在内核上运行用户态(User/Application mode)的终端,并输入命令执行其他程序。

源码公开:Joker001014/Jokerix (github.com)


目录

0 前置知识 【Create my OS】0 前置知识 | JokerDebug (joker001014.github.io)

复制代码
    0.1 RISC-V硬件机制
    0.2 RISC-V 汇编
    0.3 SBI 规范
    0.4 GDB 调试
    0.5 Jokerix 体系结构
    0.6 实验环境

1 最小内核 【Create my OS】1 最小内核 | JokerDebug (joker001014.github.io)

复制代码
    1.1 内核入口点
    1.2 生成内核镜像
    1.3 使用 QEMU 运行
    1.4 封装 SBI接口

2 开启中断 【Create my OS】2 开启中断 | JokerDebug (joker001014.github.io)

复制代码
    2.1 RISC-V 中断机制
    2.2 触发断点
    2.3 中断上下文
    2.4 开启时钟中断

3 内存管理 【Create my OS】3 内存管理 | JokerDebug (joker001014.github.io)

复制代码
    3.1 Buddy System
    3.2 动态内存分配
    3.3 内存按页分配框架
    3.4 基于线段树的页帧分配

4 虚拟内存 【Create my OS】4 虚拟内存 | JokerDebug (joker001014.github.io)

复制代码
    4.1 Sv39内核映射
    4.2 实现页表
    4.3 内核重映射

5 内核线程 【Create my OS】5 内核线程 | JokerDebug (joker001014.github.io)

复制代码
    5.1 线程切换
    5.2 构造线程结构
    5.3 从启动线程到新线程

6 线程调度 【Create my OS】6 线程调度 | JokerDebug (joker001014.github.io)

复制代码
    6.1 线程管理
    6.2 调度线程
    6.3 Round-Robin 调度算法
    6.4 调度测试

7 用户线程 【Create my OS】7 用户线程 | JokerDebug (joker001014.github.io)

复制代码
    7.1 创建用户程序
    7.2 实现系统调用
    7.3 进程内存空间
    7.4 创建用户进程

8 文件系统 【Create my OS】8 文件系统 | JokerDebug (joker001014.github.io)

复制代码
    8.1 SimpleFS
    8.2 打包镜像
    8.3 内核文件驱动
    8.4 文件系统测试

9 实现终端 【Create my OS】9 实现终端 | JokerDebug (joker001014.github.io)

复制代码
    9.1 键盘中断
    9.2 条件变量与输入缓冲
    9.3 echo 程序
    9.4 实现终端

编写代码文件时间线:

步骤 功能 文件(斜体表示二次修改)
1 CPU自检,跳转到Bootloader /
2 将内核代码从磁盘加载到内存(Bootloader),由OpenSBI提供:把 CPU 从 M-Mode 切换到 S-Mode,并跳转到一个固定的地址 0x80200000 /
3 编写内核入口点:设置OS启动栈,跳转到main.c执行 kernel/entry.S kernel/main.c
4 entry.Smain.c 编译和链接生成ELF文件(需存放在0x80200000),进一步生成二进制镜像文件 Makefile kernel/kernel.ld
5 QEMU加载镜像文件,至此成功运行操作系统。 /
6 封装SBI接口ecall;调用SBI接口实现 printf 功能 kernel/sbi.h kernel/printf.c
7 封装CSR读写;初始化中断处理程序入口,设置断点中断处理程序 kernel/riscv.h kernel/interrupt.c
8 保存和恢复中断上下文信息 kernel/context.h kernel/interrupt.S
9 初始化开启时钟中断,设置时钟中断处理程序 kernel/timer.c kernel/interrupt.c
10 基于二叉树的动态内存分配,采用Buddy System Allocation算法 kernel/heap.c kernel/consts.h
11 基于线段树的页帧分配 kernel/memory.c
12 设置页表,将内核运行在虚拟地址空间 kernel/kernel.ld kernel/entry.S
13 实现三级页表,将内核各个段映射到页表上 kernel/mapping.c
14 借助中断恢复机制创建内核线程,及线程上下文切换 kernel/thread.c kernel/switch.S kernel/context.h
15 线程管理框架,创建调度线程 kernel/processor.c kernel/thread.c
16 实现Round-Robin线程调度算法 kernele/rrscheduler.c
17 实现系统调用 user/syscall.h
18 实现用户态printf、动态内存分配、用户程序入口点、用户测试函数 user/io.c user/malloc.c user/entry.c user/ulib.h user/hello.c
19 编译用户程序并链接,将用户程序合并到内核 user/Makefile user/linkUser.asm
20 处理用户态系统调用 kernel/interrupt.c kernel/syscall.c
21 编译的用户程序为ELF文件,实现ELF文件加载和内存映射 kernel/elf.c kernel/mapping.c
22 创建用户线程结构(创建用户栈、创建内核栈、创建上下文) kernel/thread.c kernel/mapping.c
23 打包生成文件系统镜像fs.img,将文件系统内容合并到内核 mkfs/mksfs.c mkfs/simplefs.h kernel/linkFS.asm Makefile
24 从文件系统中找到 Inode,加载 ELF 文件数据到字节数组中 kernel/fs.c kernel/main.c kernel/thread.c
25 处理键盘中断,实现条件变量,维护等待线程队列 kernel/queue.c kernel/condition.c kernel/interrupt.c kernel/mapping.c kerne/processor.c
26 标准输入缓冲区,维护缓存内容和条件变量 kernel/stdin.c
相关推荐
小眼睛FPGA2 分钟前
【RK3568+PG2L50H开发板实验例程】Linux部分/FPGA dma_memcpy_demo 读写案例
linux·运维·科技·ai·fpga开发·gpu算力
weixin_437398219 分钟前
转Go学习笔记
linux·服务器·开发语言·后端·架构·golang
津津有味道19 分钟前
Qt C++串口SerialPort通讯发送指令读写NFC M1卡
linux·c++·qt·串口通信·serial·m1·nfc
JeffersonZU1 小时前
Linux/Unix文件IO(文件描述符、原子操作、文件数据结构、open、read、write、fcntl、dup)
linux·c语言·unix·gnu
南瓜胖胖1 小时前
【seismic unix 合并两个su文件】
服务器·unix
szekl2 小时前
HDMI 2.0 4×2矩阵切换器412HN——多信号输入输出的高清解决方案
linux·矩阵·计算机外设·电脑·ekl
weixin_399380692 小时前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes
阿巴~阿巴~2 小时前
Linux基本命令篇 —— uname命令
linux·运维·服务器
天空之城夢主2 小时前
KVM高级功能部署
linux·服务器
pipip.4 小时前
UDP————套接字socket
linux·网络·c++·网络协议·udp