TinyEMU之文件系统构建

TinyEMU之文件系统构建

  • 1 busybox简介
  • 2 编译busybox
    • 2.1 下载busybox源码
    • 2.2 进入源码目录
    • 2.3 配置busybox
    • 2.4 选择使用静态编译
    • 2.5 执行编译
  • 3 创建文件系统目录结构
    • 3.1 创建工作路径
    • 3.2 创建文件系统主要目录
    • 3.3 创建必要设备节点
    • 3.4 拷贝编译好的 busybox
    • 3.5 创建 init 文件
    • 3.6 赋予 init文件 可执行权限
  • 4 制作文件系统镜像
    • 4.1 创建 ext2 文件
    • 4.2 将目录结构拷贝进 ext2 文件
    • 4.3 创建 init 链接
    • 4.4 取消挂载

本文属于《 TinyEMU模拟器基础系列教程》之一,欢迎查看其它文章。

1 busybox简介

BusyBox作为一个集成了众多常用命令和工具的软件,用户可以直接通过命令行调用这些工具,无需单独安装每个工具。这使得BusyBox在嵌入式系统、小型Linux系统或资源受限的环境中特别有用,因为它可以显著减少系统所需的存储空间,同时提供基本的命令行操作和管理能力。

此外,BusyBox的集成性也提高了系统的可维护性和易用性。由于BusyBox包含了大量的常用命令,用户无需担心系统中缺少某些必要的工具,可以更加方便地进行系统配置、文件操作、网络管理等任务。

因此,编译好的BusyBox可执行程序,通常会被放到文件系统的/bin目录,可以使得这些命令和工具在系统启动时就被加载并可用,方便用户进行系统操作和管理。

2 编译busybox

busybox 官网:https://busybox.net/

可以通过 buildroot 或 busybox 来生成;busybox 代码量比较小,比较简单,生成的 rootfs 也比较小,因此采用busybox这种方式。

2.1 下载busybox源码

git clone https://gitee.com/mirrors/busyboxsource.git

此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/mirror/busybox

2.2 进入源码目录

cd busyboxsource

2.3 配置busybox

make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig

这里RISC-V交叉编译器安装,参考《TinyEMU之Linux Kernel编译》。

2.4 选择使用静态编译

勾选Setting->---Buildroot Options->Build static binary

2.5 执行编译

make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j128

源码目录下,生成了二进制文件: busybox。
可以通过file busybox命令来查看编译成的busybox 是哪个平台的。

busybox中,包含了大量linux命令工具,当系统启动后,就可以很方便的使用这些命令;所以,我们后续,需要将busybox放入文件系统中。

3 创建文件系统目录结构

3.1 创建工作路径

cd ..
mkdir initramfs
cd initramfs/
sudo su				# 切换到 root 账户

3.2 创建文件系统主要目录

mkdir -p {bin,sbin,dev,etc,home,mnt,proc,sys,usr,tmp}
mkdir -p usr/{bin,sbin}
mkdir -p proc/sys/kernel

3.3 创建必要设备节点

cd dev/
sudo mknod sda b 8 0 
sudo mknod console c 5 1
cd ..

在dev目录下,创建一个名为sda的块设备文件节点,执行该命令后,dev/sda文件就被创建成功。

  • ”b”表示设备类型为块设备
  • 8表示主设备号
  • 0表示次设备号

在dev目录下,创建一个名为console的字符设备文件节点,执行该命令后,dev/console文件就被创建成功。

  • ”c”表示设备类型为字符设备
  • 5表示主设备号
  • 1表示次设备号

3.4 拷贝编译好的 busybox

cp ../busyboxsource/busybox ./bin/

3.5 创建 init 文件

我们在initramfs目录下,创建init文件。
这个init文件,就是init进程,它是内核启动的第一个用户级进程。

我们把内核启动后,需要做的一些事情,写入init文件中,当内核启动后,就会自动执行它。

vim init

输入以下内容:

#!/bin/busybox sh# Make symlinks
/bin/busybox --install -s# Mount system
mount -t proc      proc      /proc
mount -t sysfs     sysfs     /sys
mount -t tmpfs     tmpfs     /tmp# Busybox TTY fix
setsid cttyhack sh# https://git.busybox.net/busybox/tree/docs/mdev.txt?h=1_32_stable
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -ssh

接下来,解释这些命令。

  • /bin/busybox --install -s :将 BusyBox 中的多个命令链接到系统的 /bin目录中,作为单独的命令来使用。
  • mount -t proc proc /proc:把proc这个虚拟文件系统挂载到/proc目录,proc文件系统由内核提供。
  • mount -t sysfs sysfs /sys:把sysfs这个虚拟文件系统挂载到/sys目录,sysfs文件系统由内核提供。
  • mount -t tmpfs tmpfs /tmp:把tmpfs这个虚拟文件系统挂载到/tmp目录,tmpfs文件系统由内核提供。
  • setsid cttyhack sh:在后台启动一个新的终端shell会话进程,并将其与当前会话分离。
  • echo /sbin/mdev > /proc/sys/kernel/hotplug:设置Linux内核的热插拔处理脚本为/sbin/mdev,当系统中有设备被热插拔(例如,USB设备被插入或拔出)时,应该调用 /sbin/mdev 这个脚本来处理这些事件。
  • mdev -s:在系统启动或动态加载驱动程序时,扫描/sys/class和/sys/block目录,查找并读取dev属性文件,获取设备编号,然后根据这些信息在/dev目录下自动创建设备节点文件。

3.6 赋予 init文件 可执行权限

chmod +x init

到这里,initramfs目录下,已经具备了一个linux文件系统的基本目录了。

在这里插入图片描述

4 制作文件系统镜像

这一节,就是把上述目录结构,打包成ext2镜像文件。

4.1 创建 ext2 文件

生成4M大小的,空白镜像文件initramfs.ext2

dd if=/dev/zero of=initramfs.ext2 bs=1M count=4

将镜像文件initramfs.ext2,格式化为ext2文件系统

mkfs.ext2 initramfs.ext2

4.2 将目录结构拷贝进 ext2 文件

创建目录

/mnt/ext2/

将initramfs.ext2,挂载到/mnt/ext2/目录

mount -t ext2 initramfs.ext2 /mnt/ext2/

挂载到/mnt/ext2/目录后,当你在 /mnt/ext2/ 下写入文件或修改文件时,这些更改会反映到 initramfs.ext2 文件中。

拷贝initramfs目录内容,至/mnt/ext2/

cp -pr initramfs/* /mnt/ext2/

4.3 创建 init 链接

进入目录

cd /mnt/ext2/sbin/

在/mnt/ext2/sbin/目录下,创建init文件的软链接

ln -s ../init .

ln -s ../init .命令:在当前目录下创建一个名为init的符号链接,这个链接指向上一级目录中的init文件或目录。
相当于,linux可以从/和/sbin/目录下,执行init脚本。

4.4 取消挂载

cd -
umount /mnt/ext2/
sync		# 强制内容立刻写入文件

到这里,我们已经对initramfs.ext2文件写入完毕,写入的内容,主要包括busybox、目录结构、init文件以及软链接等。

initramfs.ext2,即为可供 TinyEMU 启动的 root 文件系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/640388.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows系统下安装paddle

开始使用_飞桨-源于产业实践的开源深度学习平台 (paddlepaddle.org.cn) 命令行下: python -m pip install --upgrade pip --user python -m pip install paddlepaddle2.6.1 -i https://pypi.tuna.tsinghua.edu.cn/simple 报异常 ERROR: Could not install packa…

数据结构-二叉树-堆

一、物理结构和逻辑结构 在内存中的存储结构,逻辑结构为想象出来的存储结构。 二、完全二叉树的顺序存储结构 parent (child - 1)/2 leftchild 2*parent 1; rightchild 2*parent 2 上面的顺序结构只适合存储完全二叉树。如果存储,会浪费很多的空…

React自定义Hook函数:高效组件开发的秘密武器

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

LateX的基础学习

what can i say 在text.tex中写下 \documentclass{article} \begin{document]Hello \LaTeX. \end{document} 关闭记事本,cmd中dir保存,用latex text.tex来编译,可以命令行慢慢编译,这可以做成bat文件 为什么不直接开始在texst…

Meta提出全新文档级嵌入框架,利用LLM来增强信息检索能力

近年来,基于嵌入式检索(embedding-based search)或密集检索(dense retrieval)相比传统的稀疏检索(sparse retrieval)或基于词袋(bag of words)的方法,已经展示…

找不到msvcp140dll,无法继续执行代码的详细解决方法

在我们日常使用计算机进行各类工作任务的过程中,时常会遭遇一些突发的技术问题。比如,有时在运行某个重要程序或应用软件时,系统会突然弹出一个令人困扰的错误提示:“电脑提示找不到msvcp140.dll文件,因此无法继续执行…

多项式相关题()

D - S老师的虚树 值得一提的是如何求这个 a i a_i ai​,可以考虑按dfs序考虑同一种边,运用树状数组即可统计(注意不要加重了,不需要打区间覆盖,这样可以不用打线段树) F(i, 1, n) {ll sz d[i].size() - 1…

自动化测试的7个步骤

🔥 交流讨论:欢迎加入我们一起学习! 🔥 资源分享:耗时200小时精选的「软件测试」资料包 🔥 教程推荐:火遍全网的《软件测试》教程 📢欢迎点赞 👍 收藏 ⭐留言 &#x1…

微服务:Eureka原理实践:@EnableEurekaServer、@LoadBalanced

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ 微服务:Eureka原理实践&#xff1a…

国产生骨肉冻干品控好不好?热榜TOP5生骨肉冻干分享

对于新手养猫人来说,进口生骨肉冻干的高价常常让人疑惑,为何它能在养猫达人中赢得如此高的声誉?与国产生骨肉冻干相比,进口产品的价格高出数倍,那么这高昂的价格是否代表了其独特的价值,还是只是一个消费陷…

在React Router 6中使用useRouteLoaderData钩子获取自定义路由信息

在 React Router 6 中怎么像vueRouter一样,可以在配置路由的时候,定义路由的元信息(附加信息)?答案是可以的。稍有些复杂。核心是通过为每个路由定义了一个 loader 函数,用于返回自定义的路由信息,然后通过useRouteLoaderData 钩子…

力扣HOT100 - 94. 二叉树的中序遍历

解题思路&#xff1a; 递归 class Solution {List<Integer> list new ArrayList<>();public List<Integer> inorderTraversal(TreeNode root) {recur(root);return list;}public void recur(TreeNode root) {if (root null) return;recur(root.left);lis…