用busybox制作自己的rootfs

本文详细介绍BusyBox的编译过程、配置步骤以及如何构建一个基本的文件系统。包括源码下载、配置选项、编译安装、添加配置文件、设备文件创建等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1         获取源码解压

从busybox的官方主页http://www.busybox.net ,下载busybox的源码,目前最新的版本为busybox-1.13.3.tar.bz2
 

#tar –jvxf busybox-1.13.3.tar.bz2
 
进入解压后的busybox源码目录
 

#cd busybox-1.13.3
 
2         配置busybox

步骤跟编译linux内核时很像
 

#make menuconfig
 
出现一个图形界面,选择Busybox Settings,这里可以对编译、安装以及调试等模式进行配置。
 
然后选择Build Options,对交叉编译器以及编译方式进行配置。
 
其中的第一项是Build Busybox as a static binary(no shared libs),如果选择上,则busybox将以静态形式进行编译,否则将以动态方式编译。此外,还需要对交叉编译环境进行配置,选择其中的Cross Compiler Perfix,输入交叉编译器的前缀,我们的嵌入式平台上使用的是arm-uclinux-linux的交叉编译工具。
 
这里我们先选择静态编译,动态方式的稍后再讲,注意Build with Large File Support (for accessing files > 2 GB)不要选(默认是选上的),否则编译后会出现如下错误:
 

miscutils/lib.a(readahead.):In function ‘readahead_main’
 
readahead.(.text.readahead_main+0×70):undefined reference to ‘readahead’
 
collect2:ld returned 1 exit status
 
make :***[busybox_unstripped ]Error 1
 
 
 
3         编译busybox


#make
 
4         安装busybox


#make install
 
可以采用perfix参数安装到指定目录下,格式为:make install prefix=xxx目录,如果不特别指定,将默认在busybox源码目录下生成一个_install目录。到此,busybox基本上可以功成身退 了。我们需要的就是busybox编译出来的这个_install目录。
 
进入_install目录,可以看到一共有3个目录和一个文件,分别是:bin、sbin和usr目录以及linuxrc文件。
 
在对这几个目录进行说明之前,先简单介绍一下编译生成的busybox可执行文件,它存在于bin目录下。Busybox使用了带参的main 函数:int main(int argc,char *argv[]),在这个定义中,argc是传递进来的参数的个数(参数数量),而argv是一个字符串数组,代表从命令行传递进来的参数。argv的索 引0是命令行调用的程序名。可以在bin目录下进行如下操作:
 

#busybox pwd(注意,busybox这个可执行文件不需要加./)
 
当为一个可执行程序创建符号链接后,在执行这个符号链接时,就可以获取到这个符号链接的名字。而busybox正是使用符号链接的方式使一个可 执行程序看起来像很多程序一样。对于busybox中包含的每个工具来讲,都会创建一个符号链接,这样就可以使用这些符号链接来调用busybox了。然 后busybox接着根据argv[0]的值来调用内部工具。
 
下面分别对install目录下的几个文件进行一些说明。
 
Ø        bin包含用户工具,其中,busybox可执行文件就在这个目录 下,该目录下其他所有文件都是指向busybox的符号链接
 
Ø        sbin目录包含操作系统工具,同样也指向busybox。
 
Ø        linuxrc是一个链接文件,指向busybox。
 
5         添加etc目录及基本配置文件

参考一个正常的linux系统将会发现,此时busybox建立的文件系统还缺少很多文件。如果用这个作为文件系统,将是无法运行的。生成这些 配置可以选择的方法有2种,一种是直接从一个正常运行的系统中拷贝,另一种是借助于busybox的examples。显然,选择第二种会容易的多,我们 直接拷贝examples/bootfloopy/etc到install目录下。
 

#cp –a ../examples/bootfloppy/etc/ .
 
然后可以看看etc目录下的文件,一共有3个目录和文件,下面逐一对以上几个文件进行分析和说明。
 
Ø        inittab文件:系统启动后访问的第一个脚本文件,后续启动的文 件都由它指定。下面看一下busybox中原始的inittab文件内容:
 

::sysint:/etc/init.d/rcS
 
::respawn:-/bin/sh
 
tty2::askfirst:-/bin/sh
 
::ctrlaltdel:/bin/umount –a -r
 
其中第一行指定系统的启动脚本为/etc/init.d/rcS
 
第二行指定打开一个登录会话
 
第三行指定在第三个虚拟终端打开一个无须登录验证的shell
 
第四行指定了当按下ctrl+alt+del组合键时的执行命令
 
Ø        fstab文件:定义了文件系统的各个“挂载点”,需要与实际的系统 相配合。默认的fstab文件内容为:
 

proc   /proc proc defaults 0 0

其他的根据需要再进行添加,比如devpts  /dev/pts devpts defaults 0 0就是为UNIX PTYs准备的,后面讲telnetd时要用到。
 
Ø        profile文件:终端登陆之后首先运行的脚本。
 
 
 
6         添加dev目录及基本设备文件

调试时要通过串口发送消息到终端显示。因此串口控制台和终端2个设备文件是必不可少的。
 

#mkdir dev
 
#mknod dev/console c 5 1
 
#mknod dev/ttyAMA0 c 204 64
 
在启动参数中,设置console=ttyAMA0
 
7         添加其他常用目录

可以选择home、root、proc、mnt、lib、var、opt、tmp。
 
此时,一个基本的文件系统的功能就已经完成了。可以采用NFS进行调试。但是,此时你可能会遇到如下问题,系统登录后终端上会不断打印:
 

cannot open /dev/ttyS2:No such file or directory.
 
原因出在/etc目录下的inittab文件,我们看一下其内容:
 

::sysint:/etc/init.d/rcS
 
::respawn:-/bin/sh
 
tty2::askfirst:-/bin/sh
 
::ctrlaltdel:/bin/umount –a -r
 
这条语句表示在第3个虚拟终端打开一个无须登录验证的shell。而我们之前没有建立这个tty2设备,因此会出错。解决的办法有2个:一是屏 蔽该语句,二是建立该设备节点。我们选择将其屏蔽。
 
8         相关问题

8.1      使用动态方式编译 busybox

进入Build Options时,不要选择Build Busybox as a static binary,其他所有操作步骤跟静态编译一样,你会发现这样建立的文件系统无法启动,终端上打印出如下消息:
 

Kernel panic-not synving:No init found. Try passing init=option to kernel.
 
为什么会出现这种问题呢?这就得回到两种编译方式的特点上来。静态编译时是将所用到的库文件一起编译了进去,而动态编译时是在需要时才调用相应 的库。我们选择动态编译后,没有添加任何库文件就运行,显然是会出错的。那么如何查看busybox可执行文件里使用的库呢。Readelf这个工具提供 了解决办法。使用如下命令,参数d表示将文件中所有的动态部分予以显示。
 

# arm-uclibc-linux-readelf -d busybox
 
Dynamic section at offset 0xca014 contains 18 entries:
 
  标记        类型                         名称/值
 
 0×00000001 (NEEDED)                     共享库: [libm.so.0]
 
 0×00000001 (NEEDED)                     共享库: [libc.so.0]
 
 0×0000000c (INIT)                       0xbe24

 0×0000000d (FINI)                       0xb2054

 0×00000004 (HASH)                       0×80e8

 0×00000005 (STRTAB)                     0xa500

 0×00000006 (SYMTAB)                     0×8b70

 0×0000000a (STRSZ)                      3259 (bytes)

 0×0000000b (SYMENT)                     16 (bytes)

 0×00000015 (DEBUG)                      0×0

 0×00000003 (PLTGOT)                     0xda0cc

 0×00000002 (PLTRELSZ)                   3040 (bytes)

 0×00000014 (PLTREL)                     REL

 0×00000017 (JMPREL)                     0xb244

 0×00000011 (REL)                        0xb1bc

 0×00000012 (RELSZ)                      136 (bytes)

 0×00000013 (RELENT)                     8 (bytes)

 0×00000000 (NULL)                       0×0

从上面的结果中,我们可以看到,busybox这个程序使用到了libm.so.0和libc.so.0两个库文件,实际上这是2个符号链接, 分别指向libc-0.9.28.so和libuClibc-0.9.28.so。将以上四个文件分别拷贝到lib目录下。按理说,这样应该就可以了,但 是仍然无法正常运行。显示的错误信息和刚刚没加库之前一样。可能的原因有2种:一是库文件没有添加全,二是库文件没有正确被加载。根据readelf显示 的结果应该不是第一种原因。那么到底为什么没被正确加载呢?原来库文件的加载,还需要一个共享库加载器。找到对应的文件ld-uClibc- 0.9.28.so和ld-uClibc.so.0添加到lib目录下后。运行正常。
 
8.2      终端登录用户验证功 能添加

需要在etc目录下增加passwd、group和shadow(在编译busybox时如果不选择shadow功能将不需要这个文件)3个文 件。
 
生成这3个文件的方法有:
 
Ø        手动生成,按照格式规范自己编写内容;
 
Ø        通过busybox提供的工具adderuser自动生成
 
8.2.1        手动方式

首先我们介绍一下如何手动添加。以增加root用户为例,增加passwd文件,其内容为:
 

#cat passwd
 
root:x:0:0:root:/root:/bin/sh
 
同时,此时要确定root目录已经存在。
 
passwd一共由7个字段组成,6个冒号将其隔开。它们的含义分别为:
 
1     用户名
 
2     是否有加密口令,x表示有,不填表示无,采用MD5、DES加密。
 
3     用户ID
 
4     组ID
 
5     注释字段
 
6     登录目录
 
7     所使用的shell程序
 
增加group文件,其内容为:
 

#cat group
 
root:x:0:
 
Group一共由4个字段组成,3个冒号将其隔开,它们的含义分别为:
 
1     组名
 
2     是否有加密口令,同passwd
 
3     组ID
 
4     指向各用户名指针的数组
 
由于busybox默认启动了shadow模式,因此需要增加shadow文件,其内容为:
 

#cat shadow
 
root:$1$3jZ93Mwq$oaeef6lWIuThavs8wD0Wh1:0:0:99999:7:::
 
shadow一共由9个字段组成,8个冒号将其隔开,它们的含义分别为:
 
1     用户名
 
2     加密后的口令,若为空,表示该用户不需要口令即可登陆,若为*号,表示该账号被禁用。 上面的表示的是123456加密后的口令。
 
3     从1970年1月1日至口令最近一次被修改的天数
 
4     口令在多少天内不能被用户修改
 
5     口令在多少天后必须被修改(0为没有修改过)
 
6     口令过期多少天后用户账号被禁止
 
7     口令在到期多少天内给用户发出警告
 
8     口令自1970年1月1日被禁止的天数
 
9     保留域
 
这里强调一下shadow文件的由来。/etc/passwd文件对系统的所有用户都是可读的,这样的好处是每个用户都知道系统上有哪些用户, 但缺点是其他用户的口令容易受到攻击,尤其是当口令较简单时。所以一些linux系统中使用到了影子口令文件shadow,将用户的口令存储在另一个文件 /etc/shadow中,该文件只有根用户root可读,大大提高了安全性。
 
不过,采用这种手动添加文件的方法有一个缺陷,就是如果要为用户设置登陆口令的话,shadow文件中必须填写加密后的口令,而这个加密算法我 们又不知道,即使知道,要经过转换后再添加,比较麻烦。此时,不妨试一下第二种方法。
 
8.2.2        自动方式

自动生成是使用了busybox提供的adduser工具和passwd工具。
 
在文件系统正常运行起来后,使用adduser命令,使用方法为:
 

#adduser root
 
然后就会在etc目录下自动生成passwd 、group和shadow3个文件。但是运行该命令后会打印出如下消息:
 

passwd:unknown uid 0
 
这表示不能为该用户设置密码,此时你会发现要passwd命令也无法使用。
 
解决的办法是,打开passwd文件,其内容为:
 

root:x:1000:1000:Linux User…:/home/root:/bin/sh
 
将用户ID和组ID均更改为0
 
打开group文件,其内容为:
 

root:x:1000:
 
同样将组ID改为0
 
然后,passwd命令就可以正常使用了。这时为root用户设置口令:
 

#passwd root
 
根据提示输入密码。其中,root用户登陆后的目录可以手动进行更改。
 
8.3      telnetd功能 添加

busybox默认已经添加了对telnetd和telnet功能的支持,只需要完成一些相关的设置工作就可以启动这2个功能了。
 
Ø          创建/dev/pts目录
 
Ø        在/etc/fstab中添加如下信息,挂载devpts文件系统
 

devpts /dev/pts devpts defaults 0 0
 
Ø        在/dev目录下增加ptmx设备文件:
 

#mknod ptmx c 5 2
 
Ø        在rcS文件中添加如下脚本,启动telnetd
 

if [ -x /usr/sbin/telnetd ] ;
 
then
 
        telnetd&

fi
 
Ø        在/dev目录下增加null设备文件,否则上述脚本运行时会出错: 提示找不到null文件。
 

#mknod null c 1 3
 
此时,telnetd功能开机就可以启动了。

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/yzlworld/archive/2010/07/07/5717801.aspx

<think>我们有两个主要问题:1.解决u-boot编译时缺少gnutls/gnutls.h头文件的错误;2.在安装busybox1.36.1后制作rootfs文件。对于第一个问题:缺少gnutls/gnutls.h这个头文件属于gnutls开发包,通常在Linux系统中可以通过包管理器安装。由于u-boot的某些功能(如网络相关)可能依赖这个库,所以需要安装对应的开发包。对于第二个问题:制作rootfs在引用[1]中,我们注意到编译后会生成rootfs.ext2和rootfs.ext4等文件,说明制作rootfs是构建过程的一部分。通常,制作rootfs包括:-使用busybox安装基本的命令到目标目录(例如,通过`makeinstall`将busybox安装到某个目录,如`_install`)。-创建必要的目录结构(dev,proc,sys,etc,bin,sbin,usr,lib等)。-添加必要的配置文件(如inittab、rcS等,这些在busybox的examples目录下有示例)。-使用工具(如genext2fs,mkfs.ext4等)将目录制作成镜像文件。根据引用[2],我们还可以通过NFS挂载rootfs进行测试,但在制作阶段我们主要关注如何生成镜像文件。现在,结合引用[4],我们还注意到在OpenWrt中有自动挂载的配置,但是我们在制作rootfs时不需要考虑这些,除非我们的rootfs是为OpenWrt准备的。不过,这里我们制作通用的rootfs。详细步骤:问题1:缺少gnutls/gnutls.h解决方案:在Ubuntu/Debian系统上,可以安装libgnutls28-dev包:```bashsudoapt-getinstalllibgnutls28-dev```在其他Linux发行版上,包名可能略有不同(例如Fedora上可能是gnutls-devel)。问题2:制作rootfs(以ext4格式为例)的步骤:1.编译并安装busybox1.36.1:```bashmakedefconfigmakemenuconfig#可选,进行配置,比如选择静态链接,这样就不需要额外拷贝库文件make-j$(nproc)makeinstall```这会在busybox目录下生成`_install`目录,里面包含基本的命令。2.创建rootfs目录结构:```bash#假设我们在当前目录下创建rootfs目录mkdirrootfscdrootfscp-r../busybox-1.36.1/_install/*.mkdir-pdevprocsysetc/init.dtmplibusr/lib```3.创建init脚本(例如`etc/inittab`)和启动脚本(例如`etc/init.d/rcS`):-`etc/inittab`示例:```::sysinit:/etc/init.d/rcS::askfirst:-/bin/sh::ctrlaltdel:/sbin/reboot::shutdown:/sbin/swapoff-a::shutdown:/bin/umount-a-r::restart:/sbin/init```-`etc/init.d/rcS`示例(需添加可执行权限):```bash#!/bin/shmount-tprocproc/procmount-tsysfssysfs/sysmount-ttmpfstmpfs/tmp#其他挂载或启动任务echo"StartingrcS..."```然后设置可执行权限:`chmod+xetc/init.d/rcS`4.如果使用动态链接,需要将工具链的库文件拷贝到rootfs的lib目录(例如`lib/`)。如果是静态编译busybox,则可以省略。5.使用工具生成ext4镜像:```bash#假设rootfs目录在当前目录的rootfs,生成大小为128MB的ext4镜像genext2fs-drootfs-b131072-Urootfs.ext2#使用genext2fs创建ext2(也可以转成ext4)#或者使用mkfs.ext4mkdir-pimagesddif=/dev/zeroof=images/rootfs.ext4bs=1Mcount=128mkfs.ext4images/rootfs.ext4sudomount-oloopimages/rootfs.ext4/mntsudocp-rrootfs/*/mnt/sudoumount/mnt```另外,引用[3]中提到了lxc容器的配置,这与我们的rootfs制作关系不大,但注意在配置容器时可能需要类似的rootfs目录结构。因此,总结回答:针对缺少gnutls/gnutls.h的问题,安装对应的开发包。针对制作rootfs,按照上述步骤构建目录结构,添加配置,然后使用工具制作成镜像。注意:在制作rootfs时,确保busybox是静态编译(在配置中选择“Buildstaticbinary(nosharedlibs)”),这样就不需要额外拷贝库文件,简化过程。最后,引用[1]中提到的编译后会生成rootfs.ext2和rootfs.ext4,可能是构建系统自动完成了上述步骤(比如使用Buildroot或Yocto等构建系统),但用户是手动编译busybox,所以需要手动制作。相关问题:§§相关问题§§1.如何配置busybox以静态编译?2.rootfs中还需要哪些必要的配置文件?3.如何为嵌入式系统设置自动挂载(如引用[4]中的mdev配置)?4.如何通过NFS挂载rootfs进行调试(如引用[2]所示)?</think> ### 解决u-boot编译缺少gnutls/gnutls.h问题 #### 原因分析 该错误表明系统缺失**GnuTLS开发库**。GnuTLS是用于实现SSL/TLS协议的安全通信库,u-boot在启用加密功能(如HTTPS引导)时需要该库[^1]。 #### 解决方案 1. **安装GnuTLS开发包**(以Ubuntu为例) ```bash sudo apt-get update sudo apt-get install libgnutls28-dev # 安装开发头文件和库 ``` - 其他发行版对应包名: - Fedora/CentOS: `gnutls-devel` - Arch: `gnutls` 2. **重新配置u-boot** ```bash make distclean # 清理旧配置 make <your_board>_defconfig # 使用目标板配置文件 make menuconfig # 检查加密功能配置 ``` - 验证`CONFIG_FIT_SIGNATURE`和`CONFIG_CMD_LOAD_OTP`等加密相关选项状态 3. **验证安装** ```bash ls /usr/include/gnutls/gnutls.h # 确认头文件存在 ``` 4. **重新编译** ```bash make all CROSS_COMPILE=arm-linux-gnueabihf- # 替换为你的交叉编译器 ``` > 📌 注:若仍报错,检查交叉编译器是否包含GnuTLS支持(通过`arm-linux-gnueabihf-gcc -v`查看库路径) --- ### 制作Busybox 1.36.1 rootfs步骤 #### 准备工作 1. **编译Busybox** ```bash make menuconfig # 设置静态编译: Settings → Build static binary make -j$(nproc) make CONFIG_PREFIX=./rootfs install # 安装到rootfs目录 ``` #### 构建rootfs结构 ```bash cd rootfs mkdir -p dev etc/init.d proc sys tmp lib/modules usr/bin usr/sbin ``` #### 添加关键文件 1. **创建init脚本** (`sbin/init`) ```bash #!/bin/sh mount -t proc proc /proc mount -t sysfs sysfs /sys echo "Welcome to MyRootFS!" exec /bin/sh chmod +x sbin/init ``` 2. **配置inittab** (`etc/inittab`) ```ini ::sysinit:/etc/init.d/rcS ::respawn:/sbin/getty -L ttyAMA0 115200 vt100 # 串口登录 ``` 3. **启动脚本** (`etc/init.d/rcS`) ```bash #!/bin/sh /bin/mount -a echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s chmod +x etc/init.d/rcS ``` #### 生成文件系统镜像 1. **EXT4格式镜像** ```bash dd if=/dev/zero of=rootfs.ext4 bs=1M count=128 # 创建128MB镜像 mkfs.ext4 rootfs.ext4 sudo mount -o loop rootfs.ext4 /mnt sudo cp -r rootfs/* /mnt sudo umount /mnt ``` 2. **兼容u-boot的镜像**(参考[1]) ```bash mkimage -A arm -O linux -T ramdisk -C gzip \ -d rootfs.ext4 uRamdisk # 生成u-boot可加载的ramdisk ``` #### 验证方式 1. **QEMU测试** ```bash qemu-system-arm -M versatilepb -kernel zImage \ -dtb stm32mp157c-myir.dtb \ -append "root=/dev/ram0" \ -initrd uRamdisk ``` 2. **开发板加载**(参考[2][4]) 将镜像放入`output/images/`,通过tFTP/NFS引导系统 > 💡 关键配置: > - 静态编译Busybox避免库依赖问题[^2] > - 通过`mdev`实现设备节点自动创建(参考[4]的mdev配置) > - 对齐u-boot的ramdisk要求(镜像类型/压缩格式)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值