GithubHelp home page GithubHelp logo

tiny_kernel's Introduction

Tiny_Kernel

项目描述:

先加载BIOS,然后跳转到MBR进行引导接下来的程序Loader,从实模式进入保护模式,建立全局描述符表,启用内存分页机制,之后加载内核。逐步实现了线程调度, 内存管理, 进程管理。线程调度的本质是CPU定时将就绪队列中的任务切换, 这就需要实现中断定时器。内存管理采⽤位图管理, 为每个任务维护⼀个虚拟内存池。锁采⽤信号量实现

开发环境

  • 操作系统: Arch Linux
  • 类型: 64位
  • 编译器版本: GCC 12.2.1
  • nasm 版本: 2.15.05
  • bochs 版本: 2.7 安装方法

使用说明

  • 安装gcc , bochs , dd , nasm , bximage
  • 在主目录运行 make all 命令
  • 在终端运行 bochs -f bochsrc命令

项目流程

操作系统启动程序运行流程(部分)

  1. BIOS 基本输入输出, 检查各种设备的情况, 并且建立中断向量表 填写中断例程, 某些非常实用的中断是由BIOS提供的, BIOS将0柱面0磁头1扇区 的数据转移到了0x7c00位置, 并将CS:IP指向了该块位置, 默认认为0盘0道1扇区的就是启动盘, 且校验方式为看最后两个字节的魔数 是否为0x55和0xaa, 若是的话则校验成功.

  2. MBR接到了接力棒, 作为主引导程序, 完成从磁盘读入Loader加载器的使命.

  3. 初始化GDT, 从实模式进入保护模式(4GB), 打开A20, 加载GDT, cr0寄存器第0位置1, 然后刷新流水线. 这里我们用的是平坦模型 ,用LGDT指令把GDT表的位置放了进去, 并且初始化了三个段描述符: 显示段描述符, 代码段, 数据段. 从此开始了从16位实模式到了32位模式, 开启内存分页机制, 加载内核.

  4. 编写打印函数

  5. 实现中断

  6. 内存管理系统

    • 分为物理内存池,虚拟内存池。
    • 通过页表来做虚拟和物理的映射。
    • 内存池中内存单位为页,即4k。
    • 物理内存池分为内核物理内存池,用户内核内存池。 每个用户进程有自己的一个虚拟内存池,用户进程的页表把虚拟内存池的虚拟内存地址映射到用户物理内存地址,不能映射到内核物理内存池。 image
  7. 线程

  • 进程 = 资源 + 线程

  • 我们通过创建了PCB, 把我们线程所需要用到的相关内容全部放在了里面. PCB下端(我们申请的一页内存) 存放着的是我们的结构体task_struct 目前里面含有的东西不多 线程状态特权级边界魔数``还有我们的线程内核栈的地址. 我们的 中断栈所在位置 位于一页内存的最顶点位置 我们上下文切换时 如果外面有中断 我们就把我们所有的上下文环境放在那里 我们的内核栈 所在位置 是位于中断栈的下方 那里我们放着的是我们的4个寄存器 和 我们的 某些需要的函数地址

  • 切换线程

    • 先创建线程
    • 打开中断 每个时钟中断调用中断函数 减去当前时间片
    • 时间片为0 简称到期了 到期之后 调用schedule调度器 切换线程
    • schedule 把在最前面的准备队列的任务的pcb获取 把当前的放到最后
    • 之后转到switch_to 保存寄存器 上下文环境 切换esp 即切换线程
  1. 输入输出系统

    • 同步机制--锁--采用信号量实现
    • 实现线程的阻塞与唤醒
    • 实现环形输入缓冲区
  2. 进程创建

    • 先在内核中分配一页内存 为线程thread分配一页pcb
    • 初始化线程后 为我们的进程的虚拟内存位图分配内存
    • 创造线程 此线程为了调用start_process初始化函数 (备注 start_process中把进程的环境给初始化好 即可调用intr_exit iretd跑路 当然这是后话)
    • 紧接着把进程的页表空间分配好 并且初始化好
    • 把含有start_process的线程放到就绪列表中 就等着被调用了
    • 线程schedule调用后 发现pgdir非空 换页表重新装载 并调用start_process
    • start_process做了一大堆事情 并把分配了一页内存给栈空间 之后就jm intr_exit切换去了
    • 各种pop之后 cs ip ds各种寄存器已经被切换了 进入用户进程
    • 切换进程时 只需要把TSS中的esp0切换即可 即内核线程栈
  3. 实现系统调用

    • 例如进程调用getpid()后
    • 调用getpid()的函数 == 调用_syscall0宏函数 函数号放入了eax
    • _syscall0中 int 0x80 引发中断 eax此时已经是函数号了
    • int 0x80的中断处理函数就是syscall_handler syscall_handler的核心在call [syscall_table+eax*4] 我们的syscall_table是提前准备好的 就是我们各种系统调用的函数指针表 根据我们输入的函数号即可定位到对应的处理函数
    • 之后再进入intr_exit 还原上下文 中断退出 完整的系统调用结束 程序照常进行

运行截图

image

参考

  • 《操作系统真相还原》
  • 各方博客

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.