i.MX6ULL(十五) 根文件系统

Linux“三巨头”已经完成了 2 个了,就剩最后一个 rootfs( 根文件系统 ) 了,本章我们就来学
习一下根文件系统的组成以及如何构建根文件系统。这是 Linux 移植的最后一步,根文件系统
构建好以后就意味着我们已经拥有了一个完整的、可以运行的最小系统。以后我们就在这个最
小系统上编写、测试 Linux 驱动,移植一些第三方组件,逐步的完善这个最小系统。最终得到
一个功能完善、驱动齐全、相对完善的操作系统
uboot  kernel 部分特别是内核启动流程比较复杂,设计模块较多 待后续进一步了解

一 根文件系统简介

根文件系统一般也叫做 rootfs,Linux 中的根文件系统一般是 EXT4。

根文件系统首先是内核启动时所 mount(挂载)的第一个文件系统,内核代码映像文件

并没有保存在 根文件系统中,一般保存在

NAND Flash 的指定存储地址、 EMMC 专用分区中。
而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本(和 服务等加载到内存中去运行。  比如 rcS inittab
根文件系统和 Linux 内核是分开的,单独 的 Linux 内核是没法正常工作的,必须要搭配根文件系统。如果不提供根文件系统, Linux 内核 在启动的时候就会提示内核崩溃(Kernel panic) 的提示

1.1 根文件系统结构 

proc 目录
此目录一般是空的,当 Linux 系统启动以后会将此目录作为 proc 文件系统的挂载点, proc
是个虚拟文件系统,没有实际的存储设备。 proc 里面的文件都是临时存在的,一般用来存储系
统运行信息文件
opt
可选的文件、软件存放区,由用户选择将哪些文件或软件放到此目录中。一般编译过程中的产物 存放位置

二  BusyBox 构建根文件系统

BusyBox 是一个集成了大量
Linux 命令和工具的软件,像 ls mv ifconfig 等命令 BusyBox 都会提供。 BusyBox 就是一
个大的工具箱,这个工具箱里面集成了 Linux 的许多工具和命令。一般下载 BusyBox 的源码,
然后配置 BusyBox ,选择自己想要的功能,最后编译即可。
1 、例程源码 ->6 BusyBox 源码 ->busybox-1.29.0.tar.bz2  buidroot

2.1 编译根文件小系统

2.1.1、修改 Makefile,添加编译器

Uboot Linux 移植一样,打开 busybox 的顶层 Makefile ,添加 ARCH CROSS_COMPILE
的值,如下所示:
164 CROSS_COMPILE ?= /usr/local / arm / gcc - linaro - 4.9.4 - 2017.01 -
x86_64_arm - linux - gnueabihf / bin / arm - linux - gnueabihf -
......
190 ARCH ?= arm

2.1.2busybox 中文字符支持

如果默认直接编译 busybox 的话,在使用 SecureCRT 的时候中文字符是显示不正常的,中文字
符会显示为“ ? ”,比如你的中文目录,中文文件都显示为“ ? ”。不知道从哪个版本开始 busybox
中的 shell 命令对中文输入即显示做了限制,即使内核支持中文但在 shell 下也依然无法正确显
示。
所以我们需要修改 busybox 源码,取消 busybox 对中文显示的限制,打开文件 busybox-
1.29.0/libbb/printable_string.c ,找到函数 printable_string ,缩减后的函数内容如下:
1 示例代码 38.2.2.3 libbb/printable_string.c 代码段

         

2  示例代码 38.2.2.5 libbb/unicode.c 代码段

2.1.3、配置 busybox

根我们编译 Uboot Linux kernel 一样,我们要先对 busybox 进行默认的配置,有以下几种
配置选项:
①、 defconfig ,缺省配置,也就是默认配置选项。
②、 allyesconfig ,全选配置,也就是选中 busybox 的所有功能。
③、 allnoconfig ,最小配置。
我们一般使用默认配置即可,因此使用如下命令先使用默认配置来配置一下 busybox
make menuconfig

配置路径如下:
Location:
-> Settings
-> Build static binary (no shared libs)
选项“ Build static binary (no shared libs) ”用来决定是静态编译 busybox 还是动态编译,静
态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库
文件,但是编译出来的 busybox 会小很多。 这里我们不能采用静态编译!因为采用静态编译的
话 DNS 会出问题!无法进行域名解析 ,配置如图 38.2.2.3 所示:
继续配置如下路径配置项:
Location:
-> Settings
-> vi-style line editing commands
结果如图 38.2.2.4 所示

继续配置如下路径配置项:
Location:
-> Linux Module Utilities
-> Simplified modutils
默认会选中“ Simplified modutils ”,这里我们要取消勾选!!结果如图 38.2.2.5 所示:
继续配置如下路径配置项:
Location:
-> Linux System Utilities
-> mdev (16 kb) // 确保下面的全部选中,默认都是选中的
最后就是使能 busybox unicode 编码以支持中文,配置路径如下:
Location:
-> Settings
-> Support Unicode
// 选中
-> Check $LC_ALL, $LC_CTYPE and $LANG environment variables // 选中

busybox 的配置就到此结束了,大家也可以根据自己的实际需求选择配置其他的选项,不
过对于初学者笔者不建议再做其他的修改,可能会出现编译出错的情况发生。

2.1.4、编译 busybox

配置好 busybox 以后就可以编译了,我们可以指定编译结果的存放目录,我们肯定要将编
译结果存放到前面创建的 rootfs 目录中,输入如下命令:
make
make install CONFIG_PREFIX=/home/t/nfs_rootfs
COFIG_PREFIX
编译完成以后会在 busybox 的所有工具和文件就会被安装到 rootfs 目录中, rootfs 目录内容:
从图 可以看出,rootfs 目录下有 bin sbin usr 这三个目录,以及 linuxrc 这个文
件。前面说过 Linux 内核 init 进程最后会查找用户空间的 init 程序,找 到以后就会运行这个用
户空间的 init 程序,从而切换到用户态 。如果 bootargs 设置 init=/linuxrc ,那么 linuxrc 就是可以
作为用户空间的 init 程序,所以用户态空间的 init 程序是 busybox 来生成的。
busybox 的工作就完成了,但是此时的根文件系统还不能使用,还需要一些其他的文件,我
们继续来完善 rootfs。

2.2 向根文件系统添加 lib

2.2.1、向 rootfs 的“/lib”目录添加库文件

Linux 中的应用程序一般都是需要动态库的,当然你也可以编译成静态的,但是静态的可
执行文件会很大。如果编译为动态的话就需要动态库,所以我们需要向根文件系统中添加动态
库。在 rootfs 中创建一个名为“ lib ”的文件夹,命令如下:
mkdir lib
lib 文件夹创建好了,库文件从哪里来呢? lib 库文件从交叉编译器中获取,前面我们搭建
交叉编译环境的时候将交叉编译器存放到了“ /usr/local/arm/ ”目录中。交叉编译器里面有很多
的库文件,这些库文件具体是做什么的我们作为初学者肯定不知道,既然我不知道那就简单粗
暴的把所有的库文件都放到我们的根文件系统中。这样做出来的根文件系统肯定很大,但是我
们现在是学习阶段,还做不了裁剪。这就是为什么我们推荐大家购买 512MB+8GB 版本的 EMMC
核心版,如果后面要学习 QT 的话那占用的空间将更大,不裁剪的话 512MB NAND 完全不
够用的!
进入如下路径对应的目录:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux
gnueabihf/libc/lib
此目录下有很多的 *so*(* 是通配符 ) .a 文件,这些就是库文件,将此目录下所有的 *so* .a
文件都拷贝到 rootfs/lib 目录中,拷贝命令如下:
cp *so* *.a /home/t/linux/nfs_rootfs/lib/ -d
后面的“ -d ”表示拷贝符号链接,这里有个比较特殊的库文件: ld-linux-armhf.so.3 ,此库文

ld-linux-armhf.so.3 后面有个“->”,表示其是个软连接文件

cp ld-linux-armhf.so.3 /home/t/nfs_rootfs/lib/

cd  /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib

cp *so* *.a /home/t/linux/nfs_rootfs/lib/ -d

 2.2.2、向 rootfs 的“usr/lib”目录添加库文件

rootfs usr 目录下创建一个名为 lib 的目录,将如下目录中的库文件拷贝到 rootfs/usr/lib
目录下:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib
将此目录下的 so .a 库文件都拷贝到 rootfs/usr/lib 目录中,命令如下:
cp *so* *.a /home/t/nfs_rootfs/usr/lib/ -d
完成以后的 rootfs/usr/lib 目录如图 
可以使用“ du ”命令来查看一下 rootfs/lib 和 rootfs/usr/lib 这两个目录的大小,命令如下:

2.2.3 创建其他文件夹

在根文件系统中创建其他文件夹,如 devprocmntsystmp root 等,

2.3 根文件系统初步测试

测试方法就是使用 NFS 挂载,
uboot 里面的 bootargs 环境变量会设置“ root ”的值,所以我们将 root 的值改为 NFS 挂载即可。
Linux 内核源码里面有相应的文档讲解如何设置,文档为 Documentation/filesystems/nfs/
nfsroot.txt ,格式如下:
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>
根据上面的格式 bootargs 环境变量的 root 值如下:
root=/dev/nfs nfsroot=192.168.1.122:/home/t/nfs_rootfs ,proto=tcp rw
ip=192.168.1.113:192.168.1.122:192.168.1.1:255.255.255.0::eth0:off
proto=tcp ”表示使用 TCP 协议,“ rw ”表示 nfs 挂载的根文件系统为可读可写。启动开发
板,进入 uboot 命令行模式,然后重新设置 bootargs 环境变量,命令如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.122:
/home/t/linux/nfs_rootfs,proto=tcp rw ip=192.168.1.113:192.168.1.122:192.168.1.1:
255.255.255.0::eth0:off' // 设置 bootargs
saveenv
设置好以后使用“ boot ”命令启动 Linux 内核,

2.4 完善根文件系统 

2.4.1 创建/etc/init.d/rcS 文件

rcS 是个 shell 脚本, Linux 内核启动以后需要启动一些服务,而 rcS 就是规定启动哪些文件
的脚本文件。在 rootfs 中创建 /etc/init.d/rcS 文件,然后在 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
~                                                                                                                                                                                                          
7 行,使用 mount 命令来挂载所有的文件系统,这些文件系统由文件 /etc/fstab 来指定,
所以我们一会还要创建 /etc/fstab 文件。
8 9 行,创建目录 /dev/pts ,然后将 devpts 挂载到 /dev/pts 目录中。
11 12 行,使用 mdev 来管理热插拔设备,通过这两行, Linux 内核就可以在 /dev 目录
下自动创建设备节点。关于 mdev 的详细内容可以参考 busybox 中的 docs/mdev.txt 文档。
创建好文件 /etc/init.d/rcS 以后一定要给其可执行权限!
使用如下命令给予 /ec/init.d/rcS 可执行权限:
chmod 777 rcS

“mount挂载所有根文件系统的时候需要读取/etc/fstab,因为/etcfstab 里面定义了该挂载哪些文件, 好了,接下来就是创建/etc/fstab 文件

2.4.2 创建/etc/fstab 文件

rootfs 中创建 /etc/fstab 文件, fstab Linux 开机以后自动配置哪些需要自动挂载的分区,
格式如下:
<file system> <mount point> <type> <options> <dump> <pass>
#<file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
~                                                                                                                                                                                                                                 
<file system>:要挂载的特殊的设备,也可以是块设备,比如/dev/sda 等等。
<mount point> :挂载点。
<type> :文件系统类型,比如 ext2 ext3 proc romfs tmpfs 等等。
<options> :挂载选项,在 Ubuntu 中输入“ man mount ”命令可以查看具体的选项。一般使
defaults ,也就是默认选项, defaults 包含了 rw suid dev exec auto nouser async
<dump> :为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0
<pass> :磁盘检查设置,为 0 表示不检查。根目录‘ / ’设置为 1 ,其他的都不能设置为 1
其他的分区从 2 开始。一般不在 fstab 中挂载根目录,因此这里一般设置为 0

2.4.3 创建/etc/inittab 文件

inittab 的详细内容可以参考 busybox 下的文件 examples/inittab init 程序会读取/etc/inittab
这个文件,in ittab 由若干条指令组成。每条指令的结构都是一样的,由以“ : ”分隔的 4 个段组
成,格式如下:
<id>:<runlevels>:<action>:<process>
<id> :每个指令的标识符,不能重复。但是对于 busybox init 来说, <id> 有着特殊意义。
对于 busybox 而言 <id> 用来指定启动进程的控制 tty ,一 般我们将串口或者 LCD 屏幕设置为控
制 tty。
<runlevels> busybox 来说此项完全没用,所以空着。
<action> :动作,用于指定 < process > 可能用到的动作。 busybox 支持的动作如表 38.4.3.1
示:  
android  启动时的 AIL
<process> 具体的动作,比如程序、脚本或命令等。
#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 ,也就是关闭交换分区。

2.5 根文件系统其他功能测试

...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/22573.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android13 编译错误汇总

1. error: New setting keys are not allowed 一版是在Settings中添加了新的字段导致的 解决&#xff1a; 在你的字段上面加上SuppressLint("NoSettingsProvider") 继续编译应该会出现 按照提示 make api-stubs-docs-non-updatable-update-current-api 然后再…

Java反射与“整活--(IOC容器)”

文章目录 前言反射什么是反射基本操作获取类对象获取类属性获取类方法方法的执行对构造方法的操作 注解定义获取注解 整活&#xff08;IOC容器&#xff09;项目结构IOC/DI流程ApplicationContextBeanDefinitionReaderBeanDefinitionBeanWrappergetBean&#xff08;&#xff09;…

【C++顺序容器】forward_list的成员函数和非成员函数

目录 forward_list 1. forward_list的成员函数 1.1 构造、析构和赋值运算符重载 1.1.1 构造函数 1.1.2 析构函数 1.1.3 赋值运算符重载 1.2 迭代器 1.3 容量 1.4 元素访问 1.4.1 遍历方法 1.5 修改器 1.6 操作 1.7 观察者 2. forward_list的非成员函数 forward_l…

3.SpringBoot 返回Html界面

1.添加依赖spring-boot-starter-web <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>2.创建Html界面 在Resources/static 文件夹下面建立对应的html&#xff0c…

实验:如何在YOLO8中添加PnP算法来实现Head Pose Estimation

目录 前言一、步骤二、PnP估计Head Pose&#xff0c;并显示1.引入库2.结果展示 总结 前言 YOLO&#xff18;的集成度比较高&#xff0c;如何在简洁的代码中加入Head Pose的东西&#xff0c;不是一件简单的事情&#xff0e;这里介绍如何插入PnP算法实现头部姿态估计的代码&…

Linux学习之vim在光标所在处写入内容,保存退出

vim insertTest使用vim打开一个叫做insertTest新文件。 输入命令之后&#xff0c;按下Enter&#xff08;回车键&#xff09;&#xff0c;就可以进入下边的操作页面。 按i在当前光标位置处&#xff0c;就可以插入内容了。 接下来写入内容跟记事本里边是差不多的。 按一下…

python_day8_综合案例

综合案例&#xff0c;全球GDP排行榜 1、知识点补充&#xff1a;sort()方法 sort()方法&#xff1a; 列表.sort(key选择排序依据的函数,reverseTrue|False) my_list [[a, 33], [b, 55], [c, 11]]def choose_sort_key(element):return element[1] # 列表中每个元素传进来&am…

Office如何通过VSTO进行PPT插件开发?

文章目录 0.引言1.工具准备2.PPT外接程序创建和生成3.外接程序生成并使用 0.引言 VSTO&#xff08;Visual Studio Tools for Office &#xff09;是VBA的替代&#xff0c;是一套用于创建自定义Office应用程序的Visual Studio工具包。VSTO可以用Visual Basic 或者Visual C#扩展O…

(转载)从0开始学matlab(第11天)—关系运算符和逻辑运算符

选择结构的运算由一个表达式控制的&#xff0c;这个表达式的结果只有 true(1)和 false(0)。有两种形式的运算符可以在 MATLAB 中关系得到 true/false&#xff1a;关系运算符和逻辑运算符。跟 C 语言一样&#xff0c;MATLAB 没有布尔型和逻辑数据类型。MATLAB 把 0 值作为结果fa…

android JSBridge的加载时机问题

https://github.com/lzyzsd/JsBridge 也算是比较悠久和使用了。 可供参考的android和IOS&#xff0c;以及前端的使用 https://segmentfault.com/a/1190000018208609 遇到的问题&#xff1a; 比如&#xff1a; 从前端在加载WebView的时候&#xff0c;执行了某些动作&#xff0c…

FreeRTOS 低功耗模式设计 STM32平台

1. STM32F105RBT6 的三种低功耗模式 1.1 sleep睡眠模式、stop停机模式、standby 待机模式 1.2 STM32中文参考手册有介绍STM32 低功耗模式的介绍 2. FreeRTOS 采用的是时间片轮转的抢占式任务调度机制&#xff0c;其低功耗设计思路一般是&#xff1a; ① 当运行空闲任务&#…

【UE4 C++】08-生成抛射物来模拟攻击效果

步骤 新建一个C类&#xff0c;父类为Actor&#xff0c;命名为“ASMagicProjectile” 在“ASMagicProjectile.h”中添加如下代码&#xff1a; 在“ASMagicProjectile.cpp”中添加如下代码&#xff1a; 编译后在虚幻编辑器中新建一个蓝图&#xff0c;选择父类为我们刚创建的C类…