1.建立si工程

2.busybox的工作入口

他会去匹配传参,然后转到相应的函数中。

3.inittab的解析

(1)inittab的解析是在busybox/init/init.c/init_main函数中
(2)执行逻辑是:先通过parse_inittab函数解析/etc/inittab(解析的重点是将inittab中的各个action和process解析出来),然后后面先直接执行sysinit和wait和once(注意这里只执行一遍),然后在while(1)死循环中去执行respwan和askfirst。

4.busybox的优势

小,小10倍左右。那么代价是什么?

阉割掉了很多不常用的参数选项。并且多个命令代码共用。

5.rcs文件分析

inittab中包含命令:

::sysinit:/etc/init.d/rcS

且busybox中也包含执行此文件路径

/init.d/rcS文件是linux中重要的配置文件

典型的嵌入式rcs文件:

#!/bin/sh
# 脚本解释器声明:指定该脚本使用 /bin/sh 来执行(嵌入式系统中常见的轻量级 Shell)

PATH=/sbin:/bin:/usr/sbin:/usr/bin
# 设置系统环境变量 PATH,定义可执行程序的搜索路径
# 包含了嵌入式系统中最核心的系统命令目录(系统管理、基础工具、用户管理类命令)
# 确保后续执行的 mount、mdev、ifconfig 等命令能被找到

runlevel=S
prevlevel=N
# 设置运行级别相关变量:
# runlevel=S:表示当前运行级别为单用户模式(Single User Mode),是嵌入式系统启动的核心级别
# prevlevel=N:表示上一个运行级别为 N(None,无之前的运行级别)

umask 022
# 设置文件创建掩码(umask)为 022
# 作用:后续创建的文件默认权限为 644(rw-r--r--),目录默认权限为 755(rwxr-xr-x)
# 保证普通用户可读,只有所有者可写,符合嵌入式系统的权限安全规范

export PATH runlevel prevlevel
# 将上述定义的 PATH、runlevel、prevlevel 变量导出为环境变量
# 确保后续子进程(如执行的命令、子脚本)能继承这些变量

mount -a
# 执行 mount -a 命令:挂载 /etc/fstab 文件中定义的所有文件系统
# 嵌入式系统中通常会挂载根文件系统之外的分区(如 /tmp、/var、/mnt 等),或网络文件系统
# 是系统启动时挂载所有配置好的文件系统的核心步骤

echo /sbin/mdev > /proc/sys/kernel/hotplug
# 配置内核热插拔机制:告诉内核,当有硬件设备热插拔(如插入U盘、网卡)时,调用 /sbin/mdev 处理
# /proc/sys/kernel/hotplug 是内核的热插拔命令配置节点,写入 mdev 路径后
# 内核会自动触发mdev 管理设备

mdev -s
# 初始化 mdev 设备管理:
# mdev 是嵌入式系统中替代 udev 的轻量级设备管理工具
# -s 参数表示 "scan",扫描 /sys 目录下的所有设备信息
# 自动在 /dev 目录下创建对应的设备节点(如 /dev/ttyS0、/dev/sda1 等)
# 这一步是嵌入式系统识别硬件设备的关键,没有设备节点,应用程序无法访问硬件

/bin/hostname -F /etc/sysconfig/HOSTNAME
# 设置系统主机名:
# -F 参数表示从指定文件(/etc/sysconfig/HOSTNAME)中读取主机名并设置
# 替代手动执行 hostname xxx 的方式,实现主机名的配置化管理

ifconfig eth0 192.168.1.10
# 配置网卡 eth0 的静态 IP 地址为 192.168.1.10
# ifconfig 是传统的网络配置工具,嵌入式系统中常用(替代 ip 命令)
# 这一步让系统启动后直接拥有固定 IP,无需 DHCP 分配,适合嵌入式设备的固定部署场景

其实是个shell脚本,可以直接执行。

这段脚本是嵌入式 Linux 系统的核心初始化脚本(rcS),主要完成系统启动初期的基础环境配置、文件系统挂载、设备管理初始化、主机名设置和网卡 IP 配置,为系统后续运行打下基础。

那为什么我们没加载rcs文件就有path?

因为busybox在硬件编码阶段就为我们添加了环境变量

6.fstab讲解

需要挂载的文件系统表格

# /etc/fstab: static file system information.
#
# Use 'vol_id --uuid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# 	<file system> 	<mount point> 	<type> 	<options> 	<dump> 	<pass>
	proc 			/proc 			proc 	defaults 	0 		0
	sysfs 			/sys 			sysfs 	defaults 	0 		0
	tmpfs 			/var 			tmpfs 	defaults 	0 		0
	tmpfs 			/tmp 			tmpfs 	defaults 	0 		0
	tmpfs 			/dev 			tmpfs 	defaults 	0 		0

7.rcs实战

进入etc目录,创建文件tstab,编辑文件,复制以上内容,wq保存。

创建文件夹init.d。新建文件rcS,编辑文件rcS,wq保存。

修改rcs文件权限为777

chmod 777 rcS

7.1虚拟文件系统挂载

然后重启开发板,发现问题:

挂载全部失败,因为没找到挂载点,我们的没有那些目录

mount: mounting proc on /proc failed: No such file or directory
mount: mounting sysfs on /sys failed: No such file or directory
mount: mounting tmpfs on /var failed: No such file or directory
mount: mounting tmpfs on /tmp failed: No such file or directory
mount: mounting tmpfs on /dev failed: No such file or directory
/etc/init.d/rcS: line 29: can't create /proc/sys/kernel/hotplug: nonexistent dir                                               ectory
mdev: can't change directory to '/dev': No such file or directory
hostname: can't open '/etc/sysconfig/HOSTNAME': No such file or directory

Please press Enter to activate this console.

创建文件夹

root@lxy-JIAOLONG-Series:/nfs_rootfs# mkdir proc sys tmp var dev

重启开发板,无挂载失败问题

[   22.762443] VFS: Mounted root (nfs filesystem) on device 0:12.
[   22.766862] Freeing init memory: 172K
hostname: can't open '/etc/sysconfig/HOSTNAME': No such file or directory

Please press Enter to activate this console.

查看proc和sys文件夹,发现有东西

但在上位机上的文件夹中没有任何东西,证明文件挂载成功。

7.2mdev和udev

mdev是udev的一个嵌入式简化版本,用以生成硬件驱动的设备文件。

7.3hostname

hostname用以设置当前的主机名

root@lxy-JIAOLONG-Series:/nfs_rootfs# hostname
lxy-JIAOLONG-Series

rcs中的配置可以自动设置主机名字

/bin/hostname -F /etc/sysconfig/HOSTNAME
# 设置系统主机名:
# -F 参数表示从指定文件(/etc/sysconfig/HOSTNAME)中读取主机名并设置
# 替代手动执行 hostname xxx 的方式,实现主机名的配置化管理

root@lxy-JIAOLONG-Series:/nfs_rootfs/etc# mkdir sysconfig
root@lxy-JIAOLONG-Series:/nfs_rootfs/etc# cd sysconfig/
root@lxy-JIAOLONG-Series:/nfs_rootfs/etc/sysconfig# vim HOSTNAME
root@lxy-JIAOLONG-Series:/nfs_rootfs/etc/sysconfig# cat HOSTNAME 
LXY210

重启开发板,现在无任何问题

[   22.821766] Looking up port of RPC 100005/1 on 192.168.1.141
[   22.831778] VFS: Mounted root (nfs filesystem) on device 0:12.
[   22.836192] Freeing init memory: 172K

Please press Enter to activate this console.
/ #

7.4其他作用

你想在命令行初始化之前做的任何事,都可以直接在rcs文件中,直接用脚本来实现。

比如:设置网路ip地址等等

8.profile文件

这个东西就是用来完善命令提示符的。我们当前的命令提示符开头啥也没有。这个文件是busybox(init进程)调用的,认名字。

/etc/profile 是 Linux 系统中全局级别的 Shell 配置文件,主要用于设置所有用户的环境变量和启动脚本,仅在用户登录系统并启动「登录 Shell(Login Shell)」 时执行。

/ #
/ #
/ #
/ #
/ #

典型的/etc/profile文件:

# Ash profile
# vim: syntax=sh

# No core files by default
ulimit -S -c 0 > /dev/null 2>&1

USER="`id -un`"
LOGNAME=$USER
PS1='[\u@\h \W]\# '
PATH=$PATH

HOSTNAME=`/bin/hostname`

export USER LOGNAME PS1 PATH

修改完成之后,当前效果:

Please press Enter to activate this console.
id: unknown ID 0
[@LXY210 ]#
[@LXY210 ]#
[@LXY210 ]#

但是没有登陆用户名

9.用户登录

为什么之前不需要登录?因为我们的inittab中包含命令:

::askfirst:-/bin/sh

让我们的设备直接运行了命令行跳过了登录

9.1login实现登录界面

busybox中集成的程序/bin/login或者/sbin/getty可以实现。

将inittab做出以下修改

#::askfirst:-/bin/sh
::sysinit:-/bin/login

ok现在要你登陆了,但是不知道密码,因为是单用户系统,所以用户名是root。

[   22.897647] VFS: Mounted root (nfs filesystem) on device 0:12.
[   22.902060] Freeing init memory: 172K
LXY210 login:

9.2password和shadow文件

这俩文件都是在/etc/目录下,passwd文件中存放用户的密码设置,真正的密码在shadow文件中,我们cat一下passwd文件:

root:x:0:0:root:/root:/bin/bash

root:用户名

x:密码占位符

0:用户id

0:组id

root:这个没啥用,是个注释,可以写联系方式之类的

/root:这个是用户的家目录

/bin/bash:这个是用户登录后默认执行的脚本

我们再cat一下shadow文件,这是加密密码

root:$6$c8A0S7dnQxYSr7wt$zwyMFjz4DYP9pEBHAY.aQFGsRNvlttd89V2l4dneYg69X0RCJ5gQd21ht7qUiZTOmUsqO1Mvx1VSLsuHOboi00:20468:0:99999:7:::

那我们怎么整呢?我们直接把上位机的passwd文件和shadow文件复制过来,然后在上面改

root@lxy-JIAOLONG-Series:/nfs_rootfs/etc# cp /etc/passwd ./
root@lxy-JIAOLONG-Series:/nfs_rootfs/etc# cp /etc/shadow ./

shadow打不开?改一下文件权限,然后就能打开了

chmod 777 shadow
chmod 777 passwd

把passwd文件改成这样:

root:x:0:0:root:/root:/bin/sh

然后创建一个/root目录

然后把shadow文件只剩第一行,其他全部删除

ok你可以使用自己上位机的root用户的密码来登录你的开发板了

[   23.098819] Freeing init memory: 172K
LXY210 login: root
Password:
login[56]: root login on 'console'
[root@LXY210 ~]#

=========================================================================

桌面端linux操作系统中,默认是不给root登录,只给普通用户账号登录的,因为这时候的root密码是空的,只有在su passwd root设置密码之后,才允许用户以root用户登录。

嵌入式linux操作系统中,默认没有普通用户账户,只有root账户,所以当shadow文件中的第一行也删掉的时候,root用户的密码为空,可以直接登录。登陆之后,也还是可以用passwd root来设置或者修改密码。

=========================================================================

9.3忘了密码怎么办

用u盘引导其他的系统(win pe)接管电脑后删除掉加密密码,嘿嘿嘿。

9.4getty实现登录

这个也是设置登录的程序,其实在busybox中都是符号链接而已。我们可以在inittab中用getty替换login实现同样的效果。

修改inittab如下:

#::sysinit:-/bin/login
::respawn:-/sbin/getty -L s3c2410_serial2 115200 vt100
#respawn:重复启动
#vt100:只是一个样式

然后就成功了

10.动态链接库的添加

10.1寻找动态链接库文件

我们动态链接编译的可执行文件无法在制作的根文件系统中运行,需要复制交叉编译链接工具提供的动态链接库文件。

目录:

/usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib/

那其他交叉编译工具在哪呢?你怎么知道?

find -name "*libm.so*"

就出来了

10.2动态链接库文件的添加

你把这一堆拷贝到根文件系统里面的rootfs/lib文件下,记得复制参数使用 -r

root@lxy-JIAOLONG-Series:/nfs_rootfs# cp /usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib/ . -r
root@lxy-JIAOLONG-Series:/nfs_rootfs# ls
bin  dev  etc  lib  linuxrc  proc  root  sbin  sys  tmp  usr  var
root@lxy-JIAOLONG-Series:/nfs_rootfs/lib# ls
ld-2.10.1.so               libcrypt-2.10.1.so  libm.so.6                libnss_hesiod-2.10.1.so   libresolv-2.10.1.so
ld-linux.so.3              libcrypt.so.1       libnsl-2.10.1.so         libnss_hesiod.so.2        libresolv.so.2
libanl-2.10.1.so           libc.so.6           libnsl.so.1              libnss_nis-2.10.1.so      librt-2.10.1.so
libanl.so.1                libdl-2.10.1.so     libnss_compat-2.10.1.so  libnss_nisplus-2.10.1.so  librt.so.1
libBrokenLocale-2.10.1.so  libdl.so.2          libnss_compat.so.2       libnss_nisplus.so.2       libSegFault.so
libBrokenLocale.so.1       libgcc_s.so         libnss_dns-2.10.1.so     libnss_nis.so.2           libthread_db-1.0.so
libc-2.10.1.so             libgcc_s.so.1       libnss_dns.so.2          libpcprofile.so           libthread_db.so.1
libcidn-2.10.1.so          libm-2.10.1.so      libnss_files-2.10.1.so   libpthread-2.10.1.so      libutil-2.10.1.so
libcidn.so.1               libmemusage.so      libnss_files.so.2        libpthread.so.0           libutil.so.1

两个命令都可以

cp /usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib/ . -r
或者
cp /usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib/*so* . -rdf

此时在上位机中依靠交叉编译链接工具动态链接的文件可以在开发板中执行。

10.3去掉不必要的符号链接(选做,建议不做)

so文件包含着调试符号信息,占用一定空间,可以去掉,命令:

arm-linux-strip *so*

大约节省20%的空间。

10.4写个makefile

all:
        arm-linux-gcc hello.c -o hello._static -static
        arm-linux-gcc hello.c -o hello._dynamic

clean:
        rm -f hello.out
        rm -f hello._dynamic
        rm -f hello._static

11.实现开机自启

很简单,修改rcS文件

修改/etc/rcS文件,在最后添加

./root/hello._dynamic

实现开机自启动,因为rcs文件在登录之前,所以该程序的执行也是在登陆之前。

11.1前台运行

某个程序暂用了控制台,这个程序部结束都不能使用控制台,这就是前台运行,上面开机自启程序就是前台运行的。

11.2后台运行

这程序不影响控制台的执行

./a.out &

12.打包镜像

12.1确定可用

我们用nfs挂载根文件系统,确保可用。然后在上位机用du命令查看根文件系统大小。

可以看到我们的根文件系统一共有6.5m,那我们最好多给一点空间,给10M

12.2建立镜像挂载点

root@lxy-JIAOLONG-Series:/# mkdir ext2_rootfs

12.3制作空白镜像


dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240
 
losetup  /dev/loop14 rootfs.ext2 
mkfs.ext2 -m 0 /dev/loop14 10240
mount -t ext2 /dev/loop14 /ext2_rootfs

实际执行效果:

root@lxy-JIAOLONG-Series:/# dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240
10240+0 records in
10240+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0256587 s, 409 MB/s
root@lxy-JIAOLONG-Series:/# losetup  /dev/loop14 rootfs.ext2 
root@lxy-JIAOLONG-Series:/# mkfs.ext2 -m 0 /dev/loop14 10240
mke2fs 1.45.5 (07-Jan-2020)
Creating filesystem with 2560 4k blocks and 2560 inodes

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

root@lxy-JIAOLONG-Series:/# mount -t ext2 /dev/loop14 ./ext2_rootfs
root@lxy-JIAOLONG-Series:/# cd ext2_rootfs/
root@lxy-JIAOLONG-Series:/ext2_rootfs# ls
lost+found

12.4写入内容

将制作好的根文件系统复制到挂载镜像的文件夹

root@lxy-JIAOLONG-Series:/ext2_rootfs# cp /nfs_rootfs/* ./ -rf
root@lxy-JIAOLONG-Series:/ext2_rootfs# ls
bin  dev  etc  lib  linuxrc  lost+found  proc  root  sbin  sys  tmp  usr  var

12.5卸载loop

root@lxy-JIAOLONG-Series:/# umount /dev/loop14
root@lxy-JIAOLONG-Series:/# losetup -d /dev/loop14

12.5测试

fastboot下载镜像到开发板

看看设备在不在

root@lxy-JIAOLONG-Series:/# fastboot devices 
SMDKC110-01	fastboot

ok开烧

root@lxy-JIAOLONG-Series:/# fastboot flash system ./rootfs.ext2 
target didn't report max-download-size
sending 'system' (10240 KB)...
OKAY [  2.583s]
writing 'system'...
OKAY [ 17.362s]
finished. total time: 19.945s

重启,设置bootargs

x210 # set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext2

然后boot启动

x210 # boot

完成。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐