当前位置: 首页 > news >正文

8.从零开始写LINUX内核——初始化中断控制芯片

Ubuntu 20.04 环境下开发 Linux 0.12 内核全指南

一、开发环境搭建与工具链配置

1. 核心工具链安装

Linux 0.12 内核开发需要特定版本的工具链以确保兼容性,以下是在 Ubuntu 20.04 下的安装命令:

bash

# 安装基础编译工具
sudo apt update && sudo apt install -y \
binutils gcc-multilib g++-multilib \
qemu-system-i386 make xxd \
vim git libncurses5-dev# 验证关键工具版本(Linux 0.12 兼容版本)
as --version | head -n1    # 需显示 2.34 或兼容版本
ld --version | head -n1    # 需显示 2.34 或兼容版本
qemu-system-i386 --version | head -n1  # 4.2 及以上版本

2. 源码获取与目录结构

bash

# 创建工作目录
mkdir -p ~/linux0.12-dev && cd ~/linux0.12-dev# 获取 Linux 0.12 源码(官方归档)
wget https://mirrors.edge.kernel.org/pub/linux/kernel/historic/linux-0.12.tar.gz
tar -zxvf linux-0.12.tar.gz
mv linux-0.12 linux-0.12-src# 目录结构说明
cd linux-0.12-src
ls -l
# boot/:引导相关代码(bootsect.s、setup.s)
# kernel/:内核核心代码
# fs/:文件系统实现
# lib/:库函数
# Makefile:顶层构建文件

二、引导系统开发(boot/ 目录)

1. 引导扇区(bootsect.s)

引导扇区是系统启动的第一个程序,位于磁盘第一个扇区(512 字节):

asm

/* bootsect.s - Linux 0.12 引导扇区* 功能:加载 setup 程序并跳转执行*/
.code16                          /* 16位实模式 */
.text
.global _startBOOTSEG  = 0x07c0               /* BIOS加载地址 */
INITSEG  = 0x9000               /* 重定位目标地址 */
SETUPSEG = 0x9020               /* setup程序加载地址 */
SETUPLEN = 4                    /* setup程序占用扇区数 */_start:jmpi    $BOOTSEG, $start2    /* 跳转到正确地址 */start2:/* 初始化段寄存器 */movw    %cs, %axmovw    %ax, %dsmovw    %ax, %esmovw    %ax, %ssmovw    $0xff00, %sp         /* 设置栈指针 *//* 清屏操作 */movw    $0x0600, %axxorw    %bx, %bxmovb    $0, %chmovb    $0, %clmovb    $24, %dhmovb    $79, %dlint     $0x10/* 显示引导信息 */movw    $msg1, %axmovw    %ax, %bpmovw    $0x1301, %axmovw    $0x000c, %bxmovw    $25, %cxmovb    $0, %dhmovb    $0, %dlint     $0x10/* 移动自身到0x90000 */movw    $BOOTSEG, %axmovw    %ax, %dsmovw    $INITSEG, %axmovw    %ax, %esxorw    %si, %sixorw    %di, %dimovw    $256, %cxrepmovswjmpi    $INITSEG, $gogo:/* 加载setup程序 */movw    $0x0000, %dxmovw    $0x0002, %cxmovw    $0x0200, %bxmovb    $SETUPLEN, %almovb    $0x02, %ahint     $0x13jnc     ok_load_setup/* 读盘错误处理 */xorw    %ax, %axint     $0x13jmp     gook_load_setup:/* 跳转到setup程序 */jmpi    $SETUPSEG, $0msg1:.ascii  "Loading Linux 0.12...".org    510.word   0xaa55              /* 引导标志 */

2. 编译引导扇区

bash

# 进入boot目录
cd ~/linux0.12-dev/linux-0.12-src/boot# 汇编生成二进制
as -32 -o bootsect.o bootsect.s
ld -m elf_i386 -Ttext 0x7c00 -s --oformat binary -o bootsect bootsect.o# 验证大小(必须512字节)
ls -l bootsect | awk '{print $5 " bytes (should be 512)"}'

三、Setup 程序开发(setup.s)

Setup 程序负责实模式到保护模式的过渡:

asm

/* setup.s - Linux 0.12 系统设置程序* 功能:收集硬件信息、初始化GDT、切换到保护模式*/
.code16
.text
.global _start_setupINITSEG  = 0x9000
SETUPSEG = 0x9020_start_setup:/* 初始化段寄存器 */movw    %cs, %axmovw    %ax, %dsmovw    %ax, %es/* 收集硬件信息 */# 获取光标位置movb    $0x03, %ahxor     %bh, %bhint     $0x10movw    %dx, (0)# 获取内存大小movb    $0x88, %ahint     $0x15movw    %ax, (2)# 获取显示模式movb    $0x0f, %ahint     $0x10movw    %bx, (4)movw    %ax, (6)/* 显示setup运行信息 */movw    $msg, %axmovw    %ax, %bpmovw    $0x1301, %axmovw    $0x000c, %bxmovw    $16, %cxmovb    $3, %dhmovb    $0, %dlint     $0x10/* 准备进入保护模式 */cli/* 移动内核到低地址 */movw    $0x0000, %axcld
do_move:movw    %ax, %esaddw    $0x1000, %axcmpw    $0x9000, %axjz      end_movemovw    %ax, %dsxorw    %di, %dixorw    %si, %simovw    $0x8000, %cxrepmovswjmp     do_move
end_move:/* 加载GDT */lgdt    gdt_48/* 初始化8259A中断控制器 */call    empty_8042movb    $0xd1, %aloutb    %al, $0x64call    empty_8042movb    $0xdf, %aloutb    %al, $0x60call    empty_8042/* 切换到保护模式 */movl    %cr0, %eaxorl     $1, %eaxmovl    %eax, %cr0/* 跳转到32位内核 */.byte   0x66, 0xea.long   0x00000000.word   0x0008empty_8042:.word   0x00eb, 0x00ebinb     $0x64, %altestb   $2, %aljnz     empty_8042ret/* GDT定义 */
gdt:.word   0, 0, 0, 0.word   0x07ff, 0x0000, 0x9a00, 0x00c0.word   0x07ff, 0x0000, 0x9200, 0x00c0gdt_48:.word   0x800.word   512 + gdt, 0x9msg:.ascii  "setup running".fill   2048 - (.-_start_setup), 1, 0

编译命令:

bash

as -32 -o setup.o setup.s
ld -m elf_i386 -Ttext 0x0 -s --oformat binary -e _start_setup -o setup setup.o

四、内核编译与运行

1. 修改 Makefile(适配 Ubuntu 20.04)

需要调整顶层 Makefile 以确保兼容现代工具链:

bash

# 编辑顶层Makefile
vim ~/linux0.12-dev/linux-0.12-src/Makefile# 修改以下内容:
# CC = gcc → CC = gcc -m32
# LD = ld → LD = ld -m elf_i386
# 增加ASFLAGS = -32

2. 完整编译流程

bash

# 回到源码根目录
cd ~/linux0.12-dev/linux-0.12-src# 清理并编译
make clean
make Image# 生成软盘镜像
dd if=/dev/zero of=linux0.12.img bs=1440k count=1
dd if=boot/bootsect of=linux0.12.img bs=512 count=1 conv=notrunc
dd if=boot/setup of=linux0.12.img bs=512 count=4 seek=1 conv=notrunc
dd if=Image of=linux0.12.img bs=512 count=2875 seek=5 conv=notrunc

3. 使用 QEMU 运行

bash

qemu-system-i386 -fda linux0.12.img -boot a -vga std -no-reboot

成功运行后,QEMU 窗口将显示 Linux 0.12 的启动信息,包括内存检测和进程初始化过程。

五、常见问题解决

  1. 汇编错误:invalid instruction suffix for `push'

    • 原因:现代 as 默认使用 64 位模式
    • 解决:所有汇编命令添加-32参数(已在上述命令中包含)
  2. 链接错误:cannot generate 32-bit executable

    • 原因:缺少 32 位库支持
    • 解决:安装gcc-multiliblibc6-dev-i386
  3. QEMU 启动后黑屏

    • 原因:引导扇区标志错误
    • 解决:检查 bootsect.s 末尾是否有.word 0xaa55

通过以上步骤,你可以在 Ubuntu 20.04 环境下成功构建并运行 Linux 0.12 内核,为进一步学习内核开发打下基础。后续可逐步研究进程管理、内存管理和文件系统等核心模块的实现。

http://www.dtcms.com/a/335334.html

相关文章:

  • 实时计算 记录
  • 小杨的H字矩阵-洛谷B3924 [GESP202312 二级]
  • Python环境下载安装、以及环境配置教程(Windows版)
  • Vue组件基础解析
  • B+树索引分析:单表最大存储记录数
  • AI搜索:大模型商业落地的“第一束光”,照见了什么?
  • 车灯的技术和未来方向
  • Python列表与元组:数据存储的艺术
  • 【科研绘图系列】R语言在DOM再矿化数据分析与可视化中的应用
  • 力扣(接雨水)——基于最高柱分割的双指针
  • LLaVA
  • 胶质母细胞瘤对化疗的敏感性由磷脂酰肌醇3-激酶β选择性调控
  • MySQL 的 DDL / DML / DQL / DCL 做一次系统梳理:概念区别→常用语法→特点与注意点→实战小例子→常见面试/坑点速记
  • 解构下一-代 AI 智能体:超越 LLM,深度解析三大核心支柱——上下文、认知与行动
  • 基础数据结构
  • Linux——进程管理和计划任务管理
  • Python中*args和**kwargs
  • 基于springboot的在线视频教育管理系统设计与实现(源码+文档+部署讲解)
  • Flow-GRPO:通过在线 RL 训练 Flow matching 模型
  • 概率论基础教程第3章条件概率与独立性(二)
  • 如何解决C盘存储空间被占的问题,请看本文
  • C语言零基础第18讲:自定义类型—结构体
  • 9.从零开始写LINUX内核——设置中断描述符表
  • duiLib 实现鼠标拖动标题栏时,窗口跟着拖动
  • 深入了解 swap:作用、局限与分区建立
  • Linux sar命令详细使用指南
  • Effective C++ 条款45:运用成员函数模板接受所有兼容类型
  • Day2--滑动窗口与双指针--2090. 半径为 k 的子数组平均值,2379. 得到 K 个黑块的最少涂色次数,2841. 几乎唯一子数组的最大和
  • Linux软件编程:线程间通信
  • 【FreeRTOS】队列集