Linux系统移植:根文件系统构建
一个 Linux 系统的启动有三个关键的文件
uboot:引导 Linux 内核启动
Linux内核:实现基础内核功能
根文件系统:内核运行的支持
本节学习一下根文件系统的构建
一、什么是根文件系统
根文件(rootFS)系统不像 FATFS、FAT、EXT4、YAFFS 和 NTFS 这样的文件系统,它更像是一个文件夹或者说目录,根文件系统的根目录和子目录中会有很多的文件,这些文件是 Linux 运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等,Linux 内核启动以后挂载的第一个文件系统就根文件系统,然后 Linux 内核会从根文件系统中读取初始化脚本等等执行文件,进而维持 Linux 内核的正常运行
单独的 Linux 内核无法正常工作的,必须要有根文件系统
二、根文件系统目录
上面提到根文件系统是个目录,我们以 ubuntu 为例子,看一下根文件系统下有啥,使用 cd / 回到根目录,然后打印目录
2.1 子目录 bin
此目录下存放着系统需要的可执行文件,一般都是一些命令,如 ls、mv 等命令
2.2 子目录 dev
该目录下存放设备文件,在 Linux 下,一切皆文件,如串口 0 在该目录下就行 /dev/ttymxc0,我们通过操作文件来操作外部设备
2.3 子目录 etc
此目录下存放着各种配置文件
2.4 子目录 lib
此目录下存放着 Linux 所必须的库文件,命令和应用程序要使用这些库文件,比如 c 语言标准库什么的都在下面
2.5 子目录 mnt
文件挂载目录,如果要挂载 U盘、SD卡什么的,可以临时挂载到下面
2.6 子目录 proc
当 Linux 系统启动以后会将此目录作为 proc 文件系统的挂载点
proc 是个虚拟文件系统,没有实际的存储设备,文件都是临时存在的,一般用来存储系统运行信息文件
2.7 子目录 usr
usr 是 Unix Software Resource 的缩写,是 Unix 操作系统软件资源目录,因此 usr 目录下存放着很多软件
2.8 子目录 var
此目录存放一些可以改变的数据
2.9 子目录 sbin
用于用户存放一些可执行文件,但是此目录下的文件、命令 只有管理员才能使用,主要用于用户系统管理
2.10 子目录 sys
系统启动以后此目录作为 sysfs 文件系统的挂载点
sysfs 是一个类似于 proc 文件系统的特殊文件系统,sysfs 也是基于 ram 的文件系统,没有存储设备,数据临时存在
2.11 子目录 opt
可选的文件、软件存放区,由用户选择将哪些文件或软件放到此目录
三、BusyBox 创建根文件系统
BusyBox 是一个集成了大量 Linux 命令和工具的软件,像 ls、mv、ifconfig 等命令 BusyBox 都会提供,通过它可以快速构建文件系统,官网地址为:https://busybox.net/
我在 ubuntu 下创建一个 busybox 文件夹,用于存放 busybox,此处下 1.29.0版本的
解压包
tar -vxjf busybox-1.29.0.tar.bz2
1
3.1 修改编译选项
修改顶层 makefile,添加编译选项
3.2 配置 busybox
busybox 的配置和 linux、uboot 配置差不多,配置有下面几步:
先配置默认配置:
make defconfig
1
进一步打开图形化配置:
make menuconfig
1
有几个重要的配置需要修改:
将编译的库选为动态编译:
静态编译不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库文件,但是编译出来的 busybox 会小很多
配置界面编译路径如下:
-> Settings
-> Build static binary (no shared libs)
1
2
取消选中静态编译:
加入 vi 编辑器:
配置路径:
-> Settings
-> vi-style line editing commands
1
2
选中
取消 modutils 库:
配置路径:
-> Linux Module Utilities
-> Simplified modutils
使能 mdev:
mdev 工具用于系统启动和热插拔或动态加载驱动程序时,自动创建设备节点
配置路径:
-> Linux System Utilities
-> mdev (16 kb)
1
2
启动全部
设置完成保存设置
3.3 编译 busybox
make
1
编译完成后将busybox安装到nfs目录下,方便调试
make install CONFIG_PREFIX=/home/jeck/linux/nfs/rootfs
1
安装完成后,安装目录下出现如下内容:
rootfs 目录下有 bin、sbin 和 usr 这三个目录,以及 linuxrc 文件,linuxrc 是用户空间的 init 程序
四、补全其他目录和文件
busybox 生成了三个目录和 init 文件,但除此之外还有其他的目录
4.1 lib 添加库
在 rootfs 中创建一个 lib 文件夹,lib 库文件从交叉编译器中获取,一般选择性的拷贝过去,根据实际情况裁剪,对于我这样的初学者,直接拷贝所有过去就行
cp /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/*so* /home/jeck/linux/nfs/rootfs/lib/ -d
cp /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/*.a /home/jeck/linux/nfs/rootfs/lib/ -d
cp /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib/*so* /home/jeck/linux/nfs/rootfs/lib/ -d
cp /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib/*.a /home/jeck/linux/nfs/rootfs/lib/ -d
-d 表示拷贝符号链接,因为库目录下有些文件是符号链接
拷贝完如下
4.2 usr/lib 添加库
在 rootfs 的 usr 目录下创建一个名为 lib 的目录,拷贝如下文件进去
cp /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/*so* /home/jeck/linux/nfs/rootfs/usr/lib/ -d
cp /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/*.a /home/jeck/linux/nfs/rootfs/usr/lib/ -d
拷贝完成如下:
看一下拷贝后的大小
在 emmc 大小范围内,没有超过
4.3 创建其他目录
创建其他运行需要文件夹
mkdir dev proc mnt sys tmp root
4.4 创建 /etc/init.d/rcS 文件
Linux 内核启动以后需要启动一些服务,rcS 脚本规定启动哪些文件的脚本文件,脚本内容如下:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
PATH 环境变量保存着可执行文件可能存在的目录
LD_LIBRARY_PATH 环境变量保存着库文件所在的目录
export 来导出环境变量,进行声明
mount 命令来挂载所有的文件系统,文件系统由文件/etc/fstab 来指定
创建目录/dev/pts,将 devpts 挂载到/dev/pts 目录中
echo 打印信息
mdev 来管理热插拔设备,使 Linux 内核可以在/dev 目录下自动创建设备节点
创建好文件后给其可执行权限
chmod 777 rcS
1
4.5 创建 /etc/fstab 文件
fstab 在 Linux 开机以后自动配置哪些需要自动挂载的分区,文件格式如下:
<file system> <mount point> <type> <options> <dump> <pass>
1
类型 功能
file system 要挂载的设备
mount point 挂载点
type 文件系统类型
options 挂载选项
dump 为 1 的话表示允许备份,为 0 不备份
pass 磁盘检查设置,为 0 表示不检查,一般设置为 0
文件中输入如下内容
#<file system> <mount point><type><options> <dump> <pass>
proc /procproc defaults 0 0
tmpfs /tmptmpfs defaults 0 0
sysfs /syssysfs defaults 0 0
4.6 创建 /etc/inittab 文件
init 程序会读取/etc/inittab 这个文件,inittab 由若干条指令组成,每条指令的结构相同
<id>:<runlevels>:<action>:<process>
1
参数 功能
id 每个指令的标识符,不能重复
runlevels 对 busybox 来说此项完全没用,空着
action 用于指定 process 可能用到的动作
process 具体的动作,比如程序、脚本或命令等
action 动作参数如下:
输入指令:
#etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
指令功能:
第 2 行,系统启动以后运行/etc/init.d/rcS 这个脚本文件
第 3 行,将 console 作为控制台终端,也就是 ttymxc0 串口
第 4 行,重启的话运行/sbin/init
第 5 行,按下 ctrl+alt+del 组合键的话就运行/sbin/reboot,看来 ctrl+alt+del 组合键用于重
启系统
第 6 行,关机的时候执行/bin/umount,也就是卸载各个文件系统
第 7 行,关机的时候执行/sbin/swapoff,也就是关闭交换分区
4.7 创建 /etc/resolv.conf 文件
在 rootfs 中新建文件/etc/resolv.conf,输入如下内容
nameserver 114.114.114.114
nameserver 210.45.244.1
配置域名解析服务器的 IP 地址,便于测试网络连接
五、nfs 测试 rootfs
uboot 里面的 bootargs 环境变量会设置 root 的值,用于指引系统找到 rootfs
nfs 挂载的格式如下:
root=/dev/nfs nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>
1
server-ip:服务器 IP 地址,也就是存放根文件系统主机的 IP 地址
root-dir:根文件系统的存放路径,比如我的就是/home/jeck/linux/nfs/rootfs
nfs-options:NFS 可选选项,一般不设置
client-ip:客户端 IP 地址,也就是我们开发板的 IP 地址,Linux 内核启动以后就会使用此 IP 地址来配置开发板
gw-ip:网关地址
netmask:子网掩码,一般是 255.255.255.0
hostname:客户机的名字,一般不设置,此值可以空着
device:设备名,也就是网卡名,一般是 eth0,eth1,正点原子的 I.MX6U-ALPHA 开
发板的 ENET2 为 eth0,ENET1 为 eth1。如果电脑只有一个网卡,那么基本只能是 eth0
autoconf:自动配置,一般不使用,所以设置为 off
dns0-ip:DNS0 服务器 IP 地址,不使用
dns1-ip:DNS1 服务器 IP 地址,不使用
对于我的配置,root 值入下:
root=/dev/nfs nfsroot=210.45.244.70:/home/jeck/linux/nfs/rootfs,proto=tcp rw
ip=210.45.244.17:210.45.244.70:210.45.244.1:255.255.255.0::eth0:off
进入 uboot 设置 启动参数完成后,从 nfs 挂载根文件系统,启动成功后测试目录
————————————————
版权声明:本文为CSDN博主「Top嵌入式」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45396672/article/details/123854872