[busybox] busybox生成一个最精简rootfs(上)

news/2023/11/29 7:10:32

这篇文章是承接着[rootfs]用busybox做一个rootfs(根文件系统)来的,再回看这篇我很久之前写的文章的时候,有一个问题出现在我的脑海中,创建了这个文件那个文件,但确实是每个文件都是必需的吗?

这篇文章我们就来讨论下这个问题。


1 busybox

当我们讨论精简文件问题的时候,busybox由于是直接编译出来的,我们暂且认为编译出来的所有binary都是必需的。

2 只有busybox行不行

busybox提供了rootfs所必须的文件,但是linux boot到最后的时候还会寻找root= 或者 init=,所以我们还需要这么一个文件告诉kernel一些必要的信息。
在这里我们把bootargs设为bootargs=console=ttyS0,115200 earlycon=sbi init=/sbin/init
但是实际上启动的时候会进不了console
在这里插入图片描述

3 考虑添加一个init文件

在这里我们先不去探讨为什么直接设置init=/sbin/init会卡住,这个牵涉到linux启动的一些话题,后面再讨论。
我们只是简单地添加一个init文件,同时,修改bootargs
bootargs=console=ttyS0,115200 earlycon=sbi init=/init
内容如下,不要忘记修改权限$ chmod 0777 init


#!/bin/shPATH=/sbin:/bin:/usr/sbin:/usr/bindo_mount_fs() {grep -q "$1" /proc/filesystems || returntest -d "$2" || mkdir -p "$2"mount -t "$1" "$1" "$2"
}do_mknod() {test -e "$1" || mknod "$1" "$2" "$3" "$4"
}mkdir -p /proc
mount -t proc proc /procdo_mount_fs sysfs /sys
do_mount_fs devtmpfs /dev
do_mount_fs devpts /dev/pts
do_mount_fs tmpfs /dev/shmmkdir -p /run
mkdir -p /var/rundo_mknod /dev/console c 5 1
do_mknod /dev/null c 1 3
do_mknod /dev/zero c 1 5# use the /dev/console device node from devtmpfs if possible to not
# confuse glibc's ttyname_r().
# This may fail (E.G. booted with console=), and errors from exec will
# terminate the shell, so use a subshell for the test
if (exec 0</dev/console) 2>/dev/null; thenexec 0</dev/consoleexec 1>/dev/consoleexec 2>/dev/console
fiexec /sbin/init "$@"

这时我们发现已经可以进console了。
在这里插入图片描述
但是会有一个讨厌的提示:

can't run '/etc/init.d/rcS': No such file or directory

4 /sbin/init 做了什么

加载内核后,它会立即初始化和配置计算机的内存,并配置连接到系统的各种硬件,包括所有处理器、I/O 子系统和存储设备。 然后内核创建一个根设备,以只读方式挂载根分区,并释放所有未使用的内存。此时,内核被加载到内存中并开始运行。

然而,由于没有用户应用程序允许对系统进行有意义的输入,因此系统无法完成很多工作。为了设置用户环境,内核执行/sbin/init 程序。

/sbin/init 程序(也称为 init)协调引导过程的其余部分并为用户配置环境,即pid=1的进程,运行在内核态,也是唯一一个没有通过fork()或者kernel_thread()创建的进程。当 init 命令启动时,它成为系统上自动启动的所有进程的父进程或祖父进程。
下面从代码来看init做了什么:
busybox/1.36.0/source/init/init.c#L1058

#if ENABLE_FEATURE_USE_INITTABsigaddset(&G.delayed_sigset, SIGHUP);  /* reread /etc/inittab */
#endif
......
check_delayed_sigs(&G.zero_ts);--> reload_inittab();--> parse_inittab();

再来看解析parse_inittab函数的实现:

/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,* then parse_inittab() simply adds in some default* actions (i.e., runs INIT_SCRIPT and then starts a pair* of "askfirst" shells).  If CONFIG_FEATURE_USE_INITTAB* _is_ defined, but /etc/inittab is missing, this* results in the same set of default behaviors.*/
static void parse_inittab(void)
{
#if ENABLE_FEATURE_USE_INITTABchar *token[4];parser_t *parser = config_open2("/etc/inittab", fopen_for_read);if (parser == NULL)
#endif{/* No inittab file - set up some default behavior *//* Sysinit */new_init_action(SYSINIT, INIT_SCRIPT, "");		// --> # define INIT_SCRIPT  "/etc/init.d/rcS"/* Askfirst shell on tty1-4 */new_init_action(ASKFIRST, bb_default_login_shell, "");
//TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry usersnew_init_action(ASKFIRST, bb_default_login_shell, VC_2);new_init_action(ASKFIRST, bb_default_login_shell, VC_3);new_init_action(ASKFIRST, bb_default_login_shell, VC_4);/* Reboot on Ctrl-Alt-Del */new_init_action(CTRLALTDEL, "reboot", "");/* Umount all filesystems on halt/reboot */new_init_action(SHUTDOWN, "umount -a -r", "");/* Swapoff on halt/reboot */new_init_action(SHUTDOWN, "swapoff -a", "");/* Restart init when a QUIT is received */new_init_action(RESTART, "init", "");return;}#if ENABLE_FEATURE_USE_INITTAB/* optional_tty:ignored_runlevel:action:command* Delims are not to be collapsed and need exactly 4 tokens*/while (config_read(parser, token, 4, 0, "#:",PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {/* order must correspond to SYSINIT..RESTART constants */static const char actions[] ALIGN1 ="sysinit\0""wait\0""once\0""respawn\0""askfirst\0""ctrlaltdel\0""shutdown\0""restart\0";int action;char *tty = token[0];if (!token[3]) /* less than 4 tokens */goto bad_entry;action = index_in_strings(actions, token[2]);if (action < 0 || !token[3][0]) /* token[3]: command */goto bad_entry;/* turn .*TTY -> /dev/TTY */if (tty[0]) {tty = concat_path_file("/dev/", skip_dev_pfx(tty));}new_init_action(1 << action, token[3], tty);if (tty[0])free(tty);continue;bad_entry:message(L_LOG | L_CONSOLE, "Bad inittab entry at line %d",parser->lineno);}config_close(parser);
#endif
}

根据上面的code flow,我们还需要创建一个/etc/inittab,如果不存在这个的话它会去找/etc/rcS等文件,说明如下:

# Note: BusyBox init works just fine without an inittab. If no inittab is
# found, it has the following default behavior:
#   ::sysinit:/etc/init.d/rcS
#   ::askfirst:/bin/sh
#   ::ctrlaltdel:/sbin/reboot
#   ::shutdown:/sbin/swapoff -a
#   ::shutdown:/bin/umount -a -r
#   ::restart:/sbin/init
#   tty2::askfirst:/bin/sh
#   tty3::askfirst:/bin/sh
#   tty4::askfirst:/bin/sh

5 inittab文件

busybox已经提供了一个example,这里我们直接拿过来,注意需要修改一下,因为我们没打算用账号密码登录,如果有必要,可以创建/etc/passwd文件,但是密码不是明文存储的,有兴趣的读者可以研究一下。
我们直接把这个文件夹都copy过来,
busybox-1.36.0/examples/bootfloppy/etc/inittab

::sysinit:/etc/init.d/rcS
# ::respawn:-/bin/sh		# -->注掉这一行,开机不需要登录
console::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r

6 /etc/init.d/rcS

rcS也有一个example,内容如下

#! /bin/sh/bin/mount -a

还有一种写法,就比较灵活了

#!/bin/sh# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do# Ignore dangling symlinks (if any).[ ! -f "$i" ] && continuecase "$i" in*.sh)# Source shell script for speed.(trap - INT QUIT TSTPset start. $i);;*)# No sh extension, so fork subprocess.$i start;;esac
done

这种写法会遍历/etc/init.d/下所有S打头的配置文件,可以在这里做网络或者其他一些东西的初始化。

7 /etc/profile

/etc/profile文件主要设置一些全局环境变量之类的。

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).if [ "${PS1-}" ]; thenif [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then# The file bash.bashrc already sets the default PS1.# PS1='\h:\w\$ 'if [ -f /etc/bash.bashrc ]; then. /etc/bash.bashrcfielseif [ "`id -u`" -eq 0 ]; thenPS1='# 'elsePS1='$ 'fifi
fiif [ -d /etc/profile.d ]; thenfor i in /etc/profile.d/*.sh; doif [ -r $i ]; then. $ifidoneunset i
fi

在这里插入图片描述

8 /etc/fstab

/etc/fstab文件主要设置一些文件系统的挂载点之类的。

# stock fstab - you probably want to override this with a machine specific oneproc                 /proc                proc       defaults              0  0
devpts               /dev/pts             devpts     mode=0620,ptmxmode=0666,gid=5      0  0
tmpfs                /run                 tmpfs      mode=0755,nodev,nosuid,strictatime 0  0# uncomment this if your device has a SD/MMC/Transflash slot
#/dev/mmcblk0p1       /media/card          auto       defaults,sync,noauto  0  0

更多内容请参考本文的下篇:
[busybox] busybox生成一个最精简rootfs(下)

Reference:

  1. 1.2. A Detailed Look at the Boot Process
  2. busybox启动流程简单解析:从init到shell login
  3. Bash PS1 customization examples
  4. How to Change / Set up bash custom prompt (PS1) in Linux

http://www.ppmy.cn/news/636742.html

相关文章

vsftpd:500 OOPS: vsftpd: refusing to run with writable root inside chroot ()错误的解决方法

博主历时三年倾注大量心血创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;真诚推荐给每一位读者&#xff01;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧…

简单设置浮动路由

文章目录 一.浮动路由二.设置一个浮动路由三.总结 一.浮动路由 浮动路由指的是配置两条静态路由&#xff0c;默认选取链路质量优(带宽大的)作为主路径&#xff0c;当主路径田现故障时&#xff0c;由带宽较小的备份路径顶替主路径。作用是保持网络的不中断。 原理&#x…

Qt6.5.x编译报错:error: C2872: “byte”: 不明确的符号

1、编译报错&#xff1a; C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared\rpcndr.h:192: error: C2872: “byte”: 不明确的符号 C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared\rpcndr.h(192): error C2872: “byte”: 不明确的…

为Windows 7的winsxs文件夹瘦身,慎重。

刚使用Win7 系统不久&#xff0c;前段时间在清理系统垃圾时发现&#xff0c;win7系统的windows目录下的winsxs 目录占用空间非常大&#xff0c;想清理之&#xff0c;却提示无权限无法清理。随即在网上查了个究竟&#xff0c;原来winsxs是一个超大的文件仓库&#xff0c;系统所在…

windows的pagefile.sys是什么文件?pagefile.sys文件太大如何移动到D盘中?

在C盘系统下&#xff0c;有一个命名为pagefile.sys的文件占用C盘太大的空间&#xff0c;不少用户怕删除pagefile.sys文件之后会对系统造成影响&#xff0c;而不少用户想要将pagefile.sys文件移动到D盘中。那么pagefile.sys是什么文件&#xff1f;Win10系统下pagefile.sys文件太…

ChatGPT is not all you need,一文看尽SOTA生成式AI模型:6大公司9大类别21个模型全回顾(一)

文章目录 ChatGPT is not all you need&#xff0c;一文看尽SOTA生成式AI模型&#xff1a;6大公司9大类别21个模型全回顾&#xff08;一&#xff09;Text-to-Image 模型DALL-E 2IMAGENStable DiffusionMuse Text-to-3D 模型DreamfusionMagic3D ChatGPT is not all you need&…

惊艳的产品背后,是锐利的设计思维

缘起 几年前&#xff0c;我偶然用一个 叫 Zine 的小app 写了两篇文章&#xff0c;感觉非常好。 后来在网上认识 了Zine 团队的创始人 Louis&#xff0c;也喜欢上了他们的另一个 App&#xff1a;Varlens&#xff0c; 最近他们推出了记笔记的 App Lattics&#xff0c;一些功能也…

闲话中国人的竖式乘法和埃及人的二分乘法

世界上所有区域的文明发源地&#xff0c;均发展了数学&#xff0c;并且将数学发展到了异常发达的地步&#xff0c;无论是埃及&#xff0c;美索不达米亚&#xff0c;印度&#xff0c;还是较晚的中国。并且这些文明发展数学的目的&#xff0c;均是为了解决实际问题的。 事实证明…

详解冬奥冠军背后的AI黑科技

在北京冬奥会上有一项黑科技引发了广泛的关注&#xff0c;就是英特尔 3DAT三维运动员追踪技术&#xff08;3D Athlete Tracking&#xff0c;3DAT&#xff09;。中国速度滑冰队夺取北京冬奥会速度滑冰男子500米比赛金牌并刷新了该项目奥运纪录&#xff0c;以及北京冬奥会开幕上《…

初步了解01背包问题(分治篇)

目录 问题描述 输入格式 输出格式 基于0/1背包的迭代算法 0/1背包问题的分析 分治法 总结 问题描述 Coda非常喜欢玩“NewWorld Online”&#xff0c;受到某部动画的影响&#xff0c;他决定创建名为“梅普露”的角色&#xff0c;并把所有技能点都加到防御力上。Coda发现了…

理解矩阵,矩阵背后的现实意义

原文链接&#xff08;排版稍作调整&#xff09; http://www.360doc.com/content/14/0824/14/202378_404267225.shtml 这是很早以前已经看过的&#xff0c;最近无意中又把保存的文章翻出来时&#xff0c;想起很多朋友问过矩阵&#xff0c;虽对矩阵似懂非懂&#xff0c;但却很想…

背单词(持续更新)

文章目录 星火雅思周计划229 复习考研352-353 职场俚语1-2 7分1-23-45-67-8 haochifun1-2 GRE1-2 托福249247-248245-246243-244241-242239-240237-238Inept(a)&#xff1a;不称职的235-236233-234225-226223-224221-222219-220217-218215-216213-214211-212209-210207-208205-…

计算机网络---考前最后一背

计算机网络---考前最后一背 - 幕布第一章&#xff1a;计算机网络与因特网第二章&#xff1a;应用层第三章&#xff1a;运输层https://www.mubucm.com/doc/4GARPAjNSRw 各章ppt总结 第1章计算机网络和因特网 - 幕布01 计算机网络和Internet发展史02 什么是Internet?03 网络边缘…

手机拍照成像误区解读

500万强于800万 手机拍照成像误区解读 平时我们购买手机的时候&#xff0c;在手机摄像头这一栏的描述里&#xff0c;总会听到有人这样去问&#xff1a;“拍照是多少万像素的&#xff1f;拍的清楚吗&#xff1f;”。究其原因&#xff0c;还是很多朋友对于影响拍照质量的关键因素…

中国金融牌照全解读

前言: 金融牌照,即金融机构经营许可证,是批准金融机构开展业务的正式文件。目前金融许可证由银监会、证监会和保监会等部门分别颁发。金融监管根据时段划分为事前监管、事中监管、事后监管,市场准入制度是事前监管的核心,金融许可证则是市场准入制度的常态表现。 近年来…

Camera和Image sensor技术基础笔记(1) -- 光和CCD/CMOS sensor基础知识

光 首先来看看可见光在电磁波谱里的位置&#xff0c;光在电磁波谱里的范围是非常窄的 一般人的眼睛能感知的电磁波的频率在380~750THz&#xff0c;波长在780&#xff5e;400nm之间&#xff0c;但有些人能够感知到频率大约在340~790THz&#xff0c;波长大约在880&#xff5e;380…

新冠疫情防控背后有哪些鲜为人知的技术?

1. 前言 从2019年末从武汉市发现新冠肺炎病毒确诊病例开始&#xff0c;到现在已经有两年多的时间了。在这两年中&#xff0c;从最初的恐慌变得自信&#xff0c;从开始的逃离疫区、抢购物资、扎堆就医&#xff0c;到现在配合流调、主动检测、积极接种疫苗已成了习惯。通过这两年…

享元模式(Flyweight)

别名 缓存&#xff08;Cache&#xff09;。 定义 享元是一种结构型设计模式&#xff0c;它摒弃了在每个对象中保存所有数据的方式 &#xff0c;通过共享多个对象所共有的相同状态&#xff0c;让你能在有限的内存容量中载入更多对象。 前言 1. 问题 假如你希望在长时间工作…

拒绝专业术语 为大家讲解什么是“背照式CMOS传感器”

时代发展&#xff0c;技术进步。数码相机的各种新技术层出不穷&#xff0c;导致消费者面对厂家宣传或者是相机参数列表中的一些专业词汇&#xff0c;一般都会感到非常难于理解&#xff0c;以致影响到购机前的判断。所以我们数码相机频道特撰写“拒绝专业术语”系列文章&#xf…

背照式和堆栈式摄像头元件的区别

背照式传感器 首先我们先来看一看现在普遍流行的背照式传感器和传统型的之间有什么不同。传统型摄像头的传感器的整个光电二极管位于感光芯片的最下层&#xff0c;传感器的A/D转换器和放大电路位于光电二极管的上层位置&#xff0c;所以光电二极管到透镜的距离是比较远的&#…
最新文章