计算机:操作系统的知识
Published:
操作系统,操作系统内核那些事儿
Linux kernel 编译
前置准备
linux 环境
- WSL2 Ubuntu 20.04
- 依赖:flex,bison,libelf-dev,libssl-dev 等
- 一键安装依赖可以参考 https://github.com/microsoft/WSL2-Linux-Kernel?tab=readme-ov-file#build-instructions
源码位置:
- 进入 https://www.kernel.org/,或者搜索 Linux kernel 找到这个
- 使用 git 下载的话就点击 git:https://git.kernel.org/
- 有很多 repo,从里面搜索 Torvalds,找到
kernel/git/torvalds/linux.git
- 点进去下方就有下载方式,git clone 或者 wget *.tar.gz 都可以,推荐 wget,源码特别大
busybox
- 用户空间的工具集,否则启动之后没有任何工具可以使用
- 链接:https://www.busybox.net/
- git clone,或者 wget *.tar.bz2:
wget https://busybox.net/downloads/busybox-1.37.0.tar.bz2
开始编译
编译 kernel
- make defconfig
- (optional)make menuconfig
- make -j$(nproc)
- 编译产物会显示:./arch/x86_64/boot/bzImage
编译 busybox
- 从源码编译
- make defconfig
- make nemuconfig
- 打开:Settings —> Build static binary (no shared libs)
- 关闭:Networking Utilities —> tc (8.3 kb)
- make -j$(nproc)
- make install
打包 initramfiles
- mkdir rootfs
- cp -r busybox-1.37.0/_install/* rootfs/
- vim init,内容如下
- #!/bin/sh
- echo “hello masteryi! this is your initramfs!”
- /bin/sh
- chmod +x init
find . | cpio -o -H newc | gzip > ../initramfs.cpio.gz
使用 qemu 仿真
使用 qemu 仿真
- sudo apt install qemu-system-x86
- qemu-system-x86_64 -kernel linux-6.16-rc2/arch/x86_64/boot/bzImage -initrd initramfs.cpio.gz -nographic -append “console=ttyS0”
- 可以看到日志出现了“hello masteryi! this is your initramfs!”
- 使用
ctrl+A, x
退出 qemu
替换 WSL 的内核
将编译好的 vmlinux 拷贝到 Windows 下的路径
设置.wslconfig,这一步只替换 kernel,不影响发行版
- 查看状态,running的话关机
- wsl -l -v
- wsl –shutdown
- vim ~/.wslconfig
- [wsl2]
- kernel=D:\project\vmlinux
- wsl -d ubuntu
查看 2 次的
uname -a
,发现 kernel 版本已经变了
替换 WSL 的用户空间
- 将 rootfs 打包:
tar -zcvf ../initramfs.tar.gz .
- 拷贝到 Windows 下的路径
- wsl –import mylinux D:\project\wsl_mylinux D:\project\initramfs.tar.gz
- wsl -d mylinux
编译 ISO 镜像文件
- sudo apt install isolinux syslinux genisoimage
- make isoimage FDARGS=”initrd=../initramfs.cpio.gz console=ttyS0” FDINITRD=../initramfs.cpio.gz
- qemu-system-x86_64 -cdrom arch/x86/boot/image.iso -nographic
编译 hd 镜像文件
和编译 ISO 基本是一样的
- sudo apt install ovmf(安装了还是找不到*** Need a shell.efi file for x64, please install EDK2/OVMF.)
- make hdimage FDARGS=”initrd=../initramfs.cpio.gz console=ttyS0” FDINITRD=../initramfs.cpio.gz
- qemu-system-x86_64 -hda arch/x86/boot/hdimage -nographic
但是安装 ovmf 后还是没有 shell.efi 这个东西,似乎是 ubuntu 的已知问题,于是源码下载,发现 master 分支没有这个文件,只能通过已有的 release 链接下载:
- wget https://github.com/tianocore/edk2/blob/UDK2018/ShellBinPkg/UefiShell/X64/Shell.efi(无效)
- wget https://github.com/tianocore/edk2/raw/UDK2018/ShellBinPkg/UefiShell/X64/Shell.efi
GitHub 的 blob URL 会返回一个 HTML 页面(包含代码渲染),而不是二进制文件 Shell.efi。所以下载还是要用 raw 的。
- sudo cp Shell.efi /usr/share/OVMF
但是编译好 hdimage 后,还是无法通过 qemu 来测试,因为没有 bootloader,需要自己制作。直接使用 qemu 就会出现 Boot failed: not a bootable disk 的问题。
具体的制作脚本可以参考:https://github.com/masteryi-0018/software-notes/blob/main/shell/test.sh
通过qemu-system-x86_64 -hda hd.img --nographic
成功启动!但是话说回来,其实并没有 hdimage 什么事。
编译 seabios
- git clone https://git.seabios.org/seabios.git(这个比较慢)
- git clone git@github.com:coreboot/seabios.git(github 镜像,快一些)
命令
- cd seabios
- make
- qemu-system-x86_64 -bios out/bios.bin –nographic
这时候就可以用自己的 bios 和自己制作的带有 bootloader 的 linux os 来测试了:
- qemu-system-x86_64 -hda hd.img -bios seabios/out/bios.bin –nographic
问题
为什么不能 apt install busybox?如果这样安装的话,会有依赖本地的动态库:
- $: ldd /usr/bin/busybox
- linux-vdso.so.1 (0x00007fff0cff3000)
- libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f8b0c435000)
- libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8b0c243000)
- /lib64/ld-linux-x86-64.so.2 (0x00007f8b0c514000)
为什么需要手动设置 busybox?如果动态链接,还是有一样的问题;tc 这个是头文件,我也懒得继续 debug 了
安装操作系统
也就是通常讲的装系统,普罗大众会接触到的概念。给一个电脑安装操作系统,或者重装操作系统,最通常的情况是制作 U 盘启动盘。我们一般在另一个可以运行的电脑上下载对应的操作系统,这里一般是 ISO,也就是镜像,这个镜像也不直接搞到对应电脑的硬盘中,所以我们用 U 盘是最省事的,但是这个 ISO 不能直接使用,需要将 U 盘制作为启动盘之后才可以使用。
启动盘的作用和以前使用光盘启动是类似的,只不过更加方便,直接将 ISO 解压到 U 盘不能用,因为这个引导程序(Bootloader)没有被放置在正确的位置上,导致无法被识别为一个操作系统。
在编译 linux kernel 的时候,有几个选项:
- fd(软盘)
- hd(硬盘)
- cdrom(光盘)
这里的 cdrom 会强制安装 bios 到 iso 中,也就是解压后能看到的isolinux.bin
和isolinux.cfg
,这个 bin 和 seabios 的 out.bin 不是一个概念的东西,bios.bin 会执行 isolinux.bin,相当于光盘的 Bootloader。
使用 qwmu 仿真的时候,也有几个对应的选项:
- kernel + initrd
- fda
- hda
- cdrom
这里 cdrom 就是对应光盘,现在使用较少,而 hd 就是对应硬盘,U 盘启动盘就是模拟硬盘的;又因为光盘和 U 盘天生不同,光盘是 ROM,在刻录时,ISO 镜像的引导信息会自动写入光盘的引导扇区,因此,只要直接刻录完整的系统 ISO 文件,光盘本身就具备启动能力。U 盘是 RAM,所以需要制作启动盘这一步。
给电脑安装
不论是 PC 或者笔记本,都属于 x86 架构的通用计算机,这里的通用基本是指拥有主板,cpu,gpu,内存,等组件的一个计算机。主板是哪个厂商的,主板上的 bios 芯片就是哪个厂商已经写好的烧录好的,我们可以制作操作系统启动盘,但也是由这个 bios 进行引导的,也就是我们控制了 bootloader,os 和 kernel 的部分。如果我们需要修改 bios,需要专门写一个 bios,并且通过烧录,移植到主板上面。
给手机安装
手机从概念上面讲,甚至是一个广义的嵌入式设备,我的理解就是以 SoC 为主导的主板高度集成,手机的 bios/uefi 也在 SoC 上只读,之后进入存储分区,开始 bootloader 以及 Android 的加载。但是手机厂商一般会将 bootloader 上锁,只有解锁了之后,才能有 root 权限,才能使用已有的 bios/uefi 安装自己的操作系统,很折腾。
给树莓派安装
计算机可以这么分:
- 通用计算机:PC,笔记本
- SBC(单板计算机):树莓派,nv jetson 等。有操作系统,实际上是一个微型计算机。
- MCU(单片机):stm32,adruino。无操作系统,软件需要烧录运行
还有一些其他的:
- fpga:Xilinx 的一些板子
- pynq/zynq:也是 Xilinx 的,但是使用了 arm+fpga 的异构体系
树莓派可以安装官方的操作系统,也可以安装 ubuntu 等 linux 发行版,所以应该也可以安装自己编译的 linux 系统,但不同的是,树莓派也是基于 arm 的架构,和手机一样,基于 arm 架构没有传统意义的 bios/uefi,叫做 bootrom,但实际上也一样,以后也就用 bios 指代这个启动过程。
给树莓派安装自定义的linux os
- 查看linux kernel支持的树莓派config,
ls arch/arm/configs/*bcm*
- 发现只有一个,安装依赖:sudo apt install gcc-aarch64-linux-gnu
- make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
- make -j$(proc)
- 查看linux kernel支持的树莓派config,
之后会有一堆选项,推荐直接按着回车不放
使用qemu仿真
- sudo apt install qemu-system-arm
- qemu-system-arm -kernel arch/x86/boot/bzImage -machine raspi2 –nographic
但是卡住了,原因还未知
启动过程
- 上电
- BIOS/UEFI:烧录在主板 bios 芯片,执行 POST(硬件自检)等
- bootloader:lilo/grub,位于 os 镜像中,执行加载 kernel
- kernel:接管资源,执行 init 进程,暴露 shell 给用户