大家好,欢迎来到IT知识分享网。
目录
一.编译/安装busybox,生成/bin、/sbin、/usr/bin、/usr/sbin目录
前言
FHS(Filesystem Hierarchy Standard)标准介绍
当我们在linux下输入ls / 的时候,见到的目录结构以及这些目录下的内容都大同小异,这是因为所有的linux发行版在对根文件系统布局上都遵循FHS标准的建议规定。
该标准规定了根目录下各个子目录的名称及其存放的内容:
| 目录名 | 存放的内容 |
| /bin | 必备的用户命令,例如ls、cp等 |
| /sbin | 必备的系统管理员命令,例如ifconfig、reboot等 |
| /dev | 设备文件,例如mtdblock0、tty1等 |
| /etc | 系统配置文件,包括启动文件,例如inittab等 |
| /lib | 必要的链接库,例如C链接库、内核模块 |
| /home | 普通用户主目录 |
| /root | root用户主目录 |
| /usr/bin | 非必备的用户程序,例如find、du等 |
| /usr/sbin | 非必备的管理员程序,例如chroot、inetd等 |
| /usr/lib | 库文件 |
| /var | 守护程序和工具程序所存放的可变,例如日志文件 |
| /proc | 用来提供内核与进程信息的虚拟文件系统,由内核自动生成目录下的内容 |
| /sys | 用来提供内核与设备信息的虚拟文件系统,由内核自动生成目录下的内容 |
| /mnt | 文件系统挂接点,用于临时安装文件系统 |
| /tmp | 临时性的文件,重启后将自动清除 |
制作根文件系统就是要建立以上的目录,并在其中建立完整目录内容。其过程大体包括
- 编译/安装busybox,生成/bin、/sbin、/usr/bin、/usr/sbin目录
- 利用交叉编译工具链,构建/lib目录
- 手工构建/etc目录
- 手工构建最简化的/dev目录
- 创建其它空目录
- 配置系统自动生成/proc目录
- 利用udev构建完整的/dev目录
- 制作根文件系统的映像文件
具体步骤
首先建立根文件系统文件 rootfs
mkdir rootfs
接下来就是生成根目录下各个子目录了
一.编译/安装busybox,生成/bin、/sbin、/usr/bin、/usr/sbin目录
1、找到SDK中提供的busybox
或者自己下载busybox
https://busybox.net/downloads/
7z x busybox.7z
cd busybox
2、修改Makefile
ARCH ?= mips
CROSS_COMPILE ?= mips-linux-gnu-
这里ARCH会从CROSS_COMPILE 提取,所以我就没有修改
备注:(如果不想修改Makefile也可以通过make menuconfig配置编译编译工具链和编译选项, Busybox Settings —>Build Options 下)
3、make menuconfig配置busybox
busybox配置主要分两部分
第一部分是Busybox Settings,主要编译和安装busybox的一些选项。这里主要需要配置:
1)、Build Options
Build BusyBox as a static binary (no shared libs),表示编译busybox时,是否静态链接C库。我们选择动态链接C库,所以这里不勾选。
2)、Installation Options (“make install” behavior)
What kind of applet links to install (as soft-links) —>(X) as soft-links,表示安装busybox时,将各个命令安装为指向busybox的软链接还是硬链接。我们选择软链接。
Installation Options (“make install” behavior) —> (./_install) BusyBox installation prefix表示busybox的安装位置,我这里用的是默认的。
3)Busybox Library Tuning
保留Command line editing以支持命令行编辑;
保留History size以支持记忆历史命令;
选中Tab completion和Username completion以支持命令自动补全
我这里默认都是选中的。
第二部分是Applets,他将busybox的支持的几百个命令分门别类。我们只要在各个门类下选择想要的命令即可。这里我们基本保持默认设置。
1)选中Networking Utilities — httpd下的Enable -u <user> option,以启用http服务器的功能allows the server to run as a specific user
4、编译安装
make defconfig 生成默认配置
make
make install
安装完成之后安装目录_install下生成了bin sbin usr/bin usr/sbin目录,其下包含了我们常用的命令,这些命令都是指向bin/busybox的软链接,而busybox本身的大小不到800K:
cp -r _install/* rootfs
如果没有busybox的话也可以从网上下载,修改项差别不大
从http://www.busybox.net/ 下载busybox-1.7.0.tar.bz2
tar xjvf busybox-1.7.0.tar.bz2解包
修改Makefile文件
二.利用交叉编译工具链,构建/lib目录
光有应用程序(命令)是不够的,因为应用程序本身需要使用C库的库函数,因此还必需制作C库,并将其放置于/lib目录
- 目标文件,如crtn.o,用于gcc链接可执行文件
- libtool库文件(.la),在链接库文件时这些文件会被用到,比如他们列出了当前库文件所依赖的其它库文件,程序运行时无需这些文件
- gconv目录,里面是各种链接脚本,在编译应用程序时,他们用于指定程序的运行地址,各段的位置等
- 静态库文件(.a),例如libm.a,libc.a
- 动态库文件 (.so、.so.[0-9]*)
- 动态链接库加载器ld-2.3.6.so、ld-linux.so.2
- 其它目录及文件
这里我们可以使用 交叉编译工具链中 现成的cp过来
找到自己的交叉编译链的安装路径
这里我们只用cp动态库就好了
如果我们只制作最简单的系统,那么我们只需要运行busybox这一个应用程序即可。
通过执行# mips-linux-gnu-readelf -a busybox | grep ‘Shared’确认busybox运行时需要用到的库
- 实际的共享链接库:libLIBRARY_NAME-GLIBC_VERSION.so。当然需要拷贝。
- 主修订版本的符号链接,指向实际的共享链接库:libLIBRARY_NAME.so.MAJOR_REVISION_VERSION,程序一旦链接了特定的链接库,将会参用该符号链接。程序启动时,加载器在加载程序前,会检索该文件。所以需要拷贝。
- 与版本无关的符号链接,指向主修订版本的符号连接(libc.so是唯一的例外,他是一个链接命令行:libLIBRARY_NAME.so,是为编译程序时提供一个通用条目)。这些文件在程序被编译时会被用到,但在程序运行时不会被用到,所以不必拷贝它。
拷贝以下文件
如果有报错Kernel panic – not syncing: Requested init /linuxrc failed (error -2).
这个错误说明/lib目录下动态库还是不完整,就要检查一下是否漏cp了
关于共享库的2个符号链接的作用的特别说明:
- 当 我们使用gcc hello.c -o hello -lm编译程序时,gcc会根据-lm的指示,加头(lib)添尾(.so)得到libm.so,从而沿着与版本无关的符号链接(libm.so -> libm.so.6)找到libm.so.6并记录在案(hello的ELF头中),表示hello需要使用libm.so.6这个库文件所代表的数学库 中的库函数。而当hello被执行的时候,动态链接库加载器会从hello的ELF头中找到libm.so.6这个记录,然后沿着主修订版本的符号链接 (libm.so.6 -> libm-2.3.6.so)找到实际的共享链接库libm-2.3.6.so,从而将其与hello作动态链接。可见,与版本无关的符号链接是供编译器 使用的,主修订版本的符号链接是供动态链接库加载器使用的,而实际的共享链接库则是供应用程序使用的。
添加厂商工具命令及依赖的动态库
方法类似。mips-linux-gnu-readelf -a 工具名称 | grep ‘Shared’。将缺失的库添加即可。
三.手工构建/etc目录
/etc 目录存放的是系统程序的主配置文件,因此需要哪些配置文件取决于要运行哪些系统程序。即使最小的系统也一定会运行1号用户进程init,所以我们至少要手 工编写init的主配置文件inittab。busybox的inittab文件的语法、语义与传统的SYSV的inittab有所不同。
inittab 文件中每个条目用来定义一个需要init启动的子进程,并确定它的启动方式,格式 为<id>:<runlevel>:<action>:<process>。例 如:ttySAC0::askfirst:-/bin/sh
- <id>表示子进程要使用的控制台,若省略则使用与init进程一样的控制台
- <runlevel>表示运行级别,busybox init程序这个字段没有意义
- <action>表示init进程如何控制这个子进程
- sysinit:系统启动后最先执行,只执行一次,init进程等待它结束后才继续执行其它动作
- wait:系统执行完sysinit条目后执行,只执行一次,init进程等待它结束后才继续执行其它动作
- once:系统执行完wait条目后执行,只执行一次,init进程不等待它结束
- respawn:启动完once进程后,init进程监测发现子进程退出时,重新启动它
- askfirst:启动完respawn进程后,与respawn类似,不过init进程先输出” Please press Enter to activate this console“,等用户输入回车后才启动子进程
- shutdown:当系统关机时
- restart:Busybox中配置了CONFIG_FEATURE_USE_INITAB,并且init进程接收到SIGUP信号时执行,先重新读取、解析/etc/inittab文件,再执行restart程序
- ctrlaltdel:按下ctrl+alt+del键时执行,不过在串口控制台中无法输入它
- <process>表示进程对应的二进制文件。如果前面有-号,表示该程序是“可以与用户进行交互的”
1)可以构建最简单的文件内容
我们可以制作最简单的/etc/inittab文件,其内容如下:
制作最简单的脚本程序文件/etc/init.d/rcS,其内容如下:
修改shell脚本文件/etc/init.d/rcS的权限,以使其可被执行:
# chmod a+x /etc/init.d/rcS
2)这里我用的是busybox 的 examples/bootfloppy/etc中的文件
etc 目录可参考系统 /etc 下的文件。其中最主要的文件包括 inittab、fstab、init.d/ rcS 文件等,这些文件最好从 busybox 的 examples/bootfloppy/etc 目录下拷贝过来,根据需求自行修改。
修改inittab文件:
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::once:/usr/sbin/telnetd -l /bin/login
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
——————————————————
修改fstab 文件 :
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
var /dev tmpfs defaults 0 0
——————————————————
修改/init.d/rcS文件:
#!/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
mkdir -p /var/lock
/bin/hostname -F /etc/hostname
# chmod a+x /etc/init.d/rcS, 记得赋权限
——————————————————
修改 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`
echo “hello world.”
echo “Done”
export USER LOGNAME PS1 PATH
——————————————————
echo “mipsT40” > etc/hostname 内容自定,将来作为主机名
3)其他文件
复制宿主机下的 /etc/passwd grop shadow 到此目录下
同时修改 /etc/inittab
console::respawn:/sbin/getty -L console vt100 # GENERIC_SERIAL
这样就会启动后就需要输入密码才能登陆了
四.手工构建最简化的/dev目录
创建两个设备节点:
#mknod console c 5 1
#mknod null c 1 3
也可以直接从系统中拷贝过来 需要的设备文件。拷贝文件时请使用 cp –R filename。
五.创建其它空目录
根据前面所列的目录,看缺少什么就创建
六.配置系统自动生成/proc目录和构建完整的/dev目录
上面的rcS已经完成了这些操作
七.制作根文件系统的映像文件
可以从以下两种文件系统中选择一种
squashfs:只读文件系统,压缩率高
jffs2:可读写文件系统,可选择压缩方式
squashfs 文件系统是一套基于 Linux 内核使用的压缩只读文件系统,压缩率高。 squashfs 具有如下特点: 优点: 压缩率高,数据(data),节点(inode)和目录(directories)都被压缩,可以节省 flash 空间,最大可以支持 4G 文件系统。 缺点: 无法写操作
squashfs文件系统制作
# mksquashfs rootfs ./rootfs.squashfs.img -b 64K –comp xz
注:制作之前请先删除要保存 squahfs 目录里面同名的 squashfs 文件
squashfs介绍和安装_mayue_web的博客-CSDN博客_squashfs
jffs2文件系统制作
# mkfs.jffs2 –d ./rootfs -l –e 0x8000 -s 0x1000 -o rootfs.jffs2.img –pad=0x
mkfs.jffs2 -o root-uclibc-1.1.jffs2 -r root-uclibc-1.1 -e 0x10000 -s 0x1000 -n -l -X zlib –pad=0x10000
参数简介:
-o, –output=FILE 指定生成文件的文件名.(default: stdout)
-r, -d, –root=DIR 指定需要制作的文件夹目录名.(默认:当前文 件夹)
-e, –eraseblock=SIZE 设定擦除块的大小为(默认: 64KB)
-s, –pagesize=SIZE 节点页大小(默认: 4KB)
-n, –no-cleanmarkers 指明不添加清楚标记(nand flash 有自己的校 检块,存放相关的信息。) 如果挂载后会出现类似:CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0 的警告,则加上-n 就会消失。
-l, –little-endian 指定使用小端格式
-X, –enable-compressor=COMPRESSOR_NAME 指压缩格式
-p, –pad[=SIZE] 通常用 16 进制表示输出文件系统大小,不足部 分用 0xff 补充
UBI文件系统制作
(1)mkfs.ubifs 制作 UBI 文件系统(不带卷集信息)
UBI 内部空间开销 大致包含:
2 个可擦除块用来存储 UBI 分区表
1 个可擦除块用来做磨损均衡
1 个可擦除块用来做 atomic LEB 更新
按每 1024 个可擦除块预留 20 个可擦除块的比例,预留空间做坏块管理(不足 1024 的,按 1024 算),假设 预留 B1
每个可擦除块,预留 2 个 page size 存储 EC header 和 VID header,如果 Nand Flash 支持 sub-pages 则每 个可擦除块预留 1 个 page size 存储 EC header 和 VID header
MTD 分区中的坏块个数 B2
坏块管理开销为 MAX(B1,B2) (B1,B2 哪个大就以哪个计算)
举例 以一个 50M 的 MTD 分区,假定可擦除块的 size 为 128KiB,共 400 个可擦除块,page size 为 2KiB,不支持 sub-pages,并且无坏块,则其 UBI 预留空间为:
(20 + 4) * 128KiB + 4KiB * (400 – 20 – 4) = 4576KiB
可以用来创建 volume 的空间为: 50M – 4576KiB = 46624KiB
一些错误的记录
1、文件系统打到内核中启动时报错
问题原因
文件系统缺少 init软连接
ln -s init bin/busybox
补充:如果不是这个原因 就要检查一下 busybox 和 lib是不是对应的,busybox 必须要使用与之对应的工具链中的库才行。
2、挂载jffs2系统报错 : jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000018: 0x2000 instead
我遇到这个问题的原因分区没擦,在uboot里面erase擦除了就好了
jffs2系统挂载不上的常见原因 · 荔枝派Zero指南 · 看云 (kancloud.cn)
总结
参考 详解制作根文件系统_复兴之路-CSDN博客
Uboot和系统移植(19)——- 根文件系统构建过程详解_big_C的博客-CSDN博客
文件系统中一些目录文件的记录
/etc/inittab
::sysinit:/etc/init.d/rcS #::respawn:-/bin/sh #::askfirst:-/bin/sh #::askfirst:-/bin/login ::askconsole:/bin/login # Stuff to do before rebooting #::ctrlaltdel:/sbin/reboot ::shutdown:/usr/bin/killall klogd ::shutdown:/usr/bin/killall syslogd ::shutdown:/bin/sync ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a # Stuff to do when restarting the init process ::restart:/sbin/init # Put a getty on the serial port 0 ::respawn:/sbin/getty -L ttyS0 vt100
屏蔽掉串口登录栏:
::respawn:/sbin/getty -L ttyS0 vt100 它指定了在特定的终端(TTYS0)上启动一个getty。这个getty将使用vt100终端类型,波特率为。
屏蔽掉此行,串口登录将会被屏蔽,如下,串口将不会有登录栏
给串口增加登录密码
::respawn:/sbin/getty -L ttyS0 vt100 即可
部分平台可能不管用,此时可以
注释掉#console::respawn:/sbin/getty -L console vt100 # GENERIC_SERIAL
添加即可
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/100292.html










