0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

i.MX6ULL嵌入式Linux开发4-根文件系统构建

码农爱学习 来源:码农爱学习 作者:码农爱学习 2022-03-14 08:41 次阅读

前面几篇介绍了uboot的移植与内核的移植,本篇进行根文件系统的构建,这是Linux移植三大组成部分的最后一步,根文件系统构建好后,就构成了一个基础的、可以运行的嵌入式Linux最小系统。

1 根文件系统简介

Linux的根文件系统一般也叫做 rootfs,Linux的根文件系统更像是一个文件夹或者叫做目录,在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文件,这些文件是Linux运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。

根文件系统的这个“根”字就说明了这个文件系统的重要性,它是其他文件系统的根,没有这个“根” ,其他的文件系统或者软件就别想工作。比如我们常用的 ls、mv、ifconfig 等命令其实就是一个个小软件,只是这些软件没有图形界面,而且需要输入命令来运行。这些小软件就保存在根文件系统中。

在构建根文件系统之前,先来看一下根文件系统里面都有些什么内容,根文件系统的目录名字为‘/’ ,就是一个斜杠:

pYYBAGIuAkyAaiJ0AAEuzUwKHZE460.png

根文件系统的各个文件夹的作用如下:

目录 描述
/bin 此目录下存放着系统需要的可执行文件,一般都是一些命令,比如 ls、mv 等命令
/dev dev 是 device 的缩写,所以此目录下的文件都是和设备有关的。在Linux下一切皆文件,即使是硬件设备,也是以文件的形式存在的,比如/dev/ttymxc0就表示串口0
/etc 此目录下存放着各种配置文件
/lib lib是library的简称,也就是库的意思,因此此目录下存放着Linux所必须的库文件
/mnt 临时挂载目录,一般是空目录,可以在此目录下创建空的子目录,比如/mnt/sd、/mnt/usb,这样就可以将SD卡或者U盘挂载到/mnt/sd 或者/mnt/usb 目录中
/proc 此目录一般是空的,当Linux系统启动以后会将此目录作为proc文件系统的挂载点,proc是个虚拟文件系统,没有实际的存储设备。proc里面的文件都是临时存在的,一般用来存储系统运行信息文件
/usr 注意,usr不是user的缩写,而是Unix Software Resource的缩写,即Unix操作系统软件资源目录。Linux 一般被称为类Unix操作系统。既然是软件资源目录,因此/usr 目录下也存放着很多软件,一般系统安装完成以后此目录占用的空间最多
/var 此目录存放一些可以改变的数据
/sbin 此目录页用户存放一些可执行文件, 但是此目录下的文件或者说命令只有管理员才能使用,主要用于系统管理
/sys 系统启动以后此目录作为 sysfs 文件系统的挂载点,sysfs是一个类似于 proc文件系统的特殊文件系统,sysfs也是基于RAM的文件系统,也就是说它也没有实际的存储设备。此目录是系统设备管理的重要目录
/opt 可选的文件、软件存放区,由用户选择将哪些文件或软件放到此目录中

2 BusyBox构建根文件系统

2.1 BusyBox简介

BusyBox是一个集成了大量的Linux命令(如ls、mv、ifconfig 等命令)和工具的软件。借助BusyBox,进行配置和编译,就可以方便的构建一个嵌入Linux平台所需要的根文件系统。

课程BusyBox官网https://busybox.net/下载源码,如下图。

poYBAGIuAl2AR7PQAAJsvpruogw085.png

左侧的“Get BusyBox”栏有一行“Download Source” ,点击“Download Source”即可打开 BusyBox 的下载页。

pYYBAGIuAmSAfu6-AABhwM2BF80510.png

目前最新的 BusyBox 版本是1.33.1,但这里使用正点原子提供的1.29.0版本的BusyBox(busybox-1.29.0.tar.bz2)

2.2 搭建NFS服务

一般在Linux驱动开发的时候都是通过NFS挂载根文件系统的,当调试好之后再将根文件系统烧写到 EMMC或者NAND中,因此需要先在ubuntu虚拟机中构建NFS服务:

sudo apt-get install nfs-kernel-server rpcbind

等待安装完成,在合适的地方新建一个名为“nfs”的文件夹,供NFS服务器使用。

如我的创建目录为:/home/xxpcb/myTest/nfs

在使用NFS之前,还需要先配置NFS,修改配置文件/etc/exports,在后面添加如下所示内容:

/home/xxpcb/myTest/nfs *(rw,sync,no_root_squash) 
poYBAGIuAm2AVQYVAACEqI4hBak521.png

最后重启NFS服务即可:

sudo /etc/init.d/nfs-kernel-server restart

正常情况会出现如下图,表示设置成功:

pYYBAGIuAnOAXaO_AABV2ZOehBk586.png

注:我第一次设置时,文件路径中的一个大小写字母搞错了,导致重启NFS时提示失败(如下图),所以在设置时要注意细节!

pYYBAGIuAnqADM1mAAFYX-Uf4-c814.png

2.3 修改配置BusyBox

在nfs服务器目录中创建一个名为rootfs的子目录,用来存放我们的根文件系统。

busybox-1.29.0.tar.bz2发送到Ubuntu中的合适位置(我存放在 /home/xxpcb/myTest/imx6ull/dts)并解压:

tar -vxjf busybox-1.29.0.tar.bz2 

解压后的文件如下:

poYBAGIuAoOAL9vsAAHuAK6Hfmw489.png

2.3.1 修改Makefile添加编译器

注:这一步可以不修改,这里修改Makefile的目的是为了在编译时,可以不用在指定编译器的架构,从而可以缩短手动输入指令的长度。但我此次测试时,修改Makefile后,输入make指令的命令进行编译时,不指定编译器,还是会提示编译器找不到之类的问题。所以,此次的测试,我就没有修改这个Makefile。

如果坚持要修改Makefile,就是修改如下的地方,指定编译器与架构(本篇进行实验时没有修改)。

pYYBAGIuAoqAMoCwAAGcI_QoPZM532.png

2.3.2 busybox中文字符支持

现在如果直接编译busybox的,在使用串口工具的时候是不支持中文显示的,中文字符会显示为“?” 。可以通过busybox源码,来取消 busybox对中文显示的限制。

打开文件busybox-1.29.0/libbb/printable_string.c,找到函数printable_string,吧某些程序注释掉,修改后的函数内容如下:

pYYBAGIuApCAOjDqAADnEiH6dIY864.png

主要就是禁止字符大于0X7F以后 break 和输出‘?’

接着打开文件busybox-1.29.0/libbb/unicode.c,修改如下内容:

poYBAGIuApaAXGOCAAFmkhaWZgE563.png

2.3.3 配置busybox

有以下几种配置选项:

defconfig:缺省配置,也就是默认配置选项

allyesconfi:全选配置,也就是选中 busybox 的所有功能

allnoconfig:最小配置

一般使用默认配置即可,因此使用如下命令先使用默认配置来配置一下 busybox:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig 
pYYBAGIuAqeARAJlAALQvpkQdLs771.png

busybox也支持图形化配置,通过图形化配置我们可以进一步选择自己想要的功能,输入如下命令打开图形化配置界面:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
pYYBAGIuAq6AJBkeAAEMTRxIHz4304.png

(1) 设置Settings -> Build static binary (no shared libs)

选项“Build static binary (no shared libs)”用来决定是静态编译还是动态编译,静态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库文件,但是编译出来的 busybox 会小很多。这里我们不使用静态编译,所以保持默认不选即可。

poYBAGIuArWABDyVAAEA2S1Jpx0254.png

(2) 设置Settings -> vi-style line editing commands

这个要勾选,通过按键“y”实现勾选,使得方括号内出现星号

pYYBAGIuAruAOt_0AAEOrvuhy8Y300.png

(3) 配置Linux Module Utilities -> Simplified modutils

默认会选中“Simplified modutils” ,这里我们要取消勾选! 使用键盘上的“n”键取消方括号中的星号。

pYYBAGIuAsGAGCn0AAEHKkm78PY359.png

(4) 配置Linux System Utilities -> mdev (16 kb)

确保下面的全部选中,默认都是选中

pYYBAGIuAsmAQIAPAAFgvkUB1T0620.png

(5) 设置Settings -> Support Unicode

要将默认没有勾选的Check $LC_ALL选中

poYBAGIuAs2AVOiIAAEhdJ-GsLU062.png

最后按两下ESC退出设置,并选择YES保持存

2.4 编译busybox构建根文件系统

输入如下指令进行编译:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install CONFIG_PREFIX=/home/xxpcb/myTest/nfs/rootfs

编译完成以后, busybox的所有工具和文件就会被安装到rootfs目录中,如下图:

poYBAGIuAtWAYl-6AAI1L5t-jzU221.png

rootfs目录下有bin、sbin和usr三个目录,以及linuxrc文件。Linux内核linit进程最后会查找用户空间的init程序,找到以后就会运行这个用户空间的init程序,从而切换到用户态。如果bootargs设置init=/linuxrc,那么linuxrc就是可以作为用户空间的init程序。

2.5 向根文件系统添加lib库

busybox编译完成后,此时的根文件系统还不能使用, 还需要一些其他的文件。

2.5.1 向rootfs/lib中添加

上面的busybox使用的是动态库编译,所以还需要向根文件系统中添加动态库

先在rootfs中创建一个名为“lib”的文件夹。lib库文件从交叉编译器中获取,之前搭建交叉编译环境的时候将交叉编译器存放到了“/usr/local/arm/”目录中,进入对应的目录:

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib 
pYYBAGIuAtyARsNKAALxaRm4duI003.png

此目录下有很多的so和.a 文件,这些就是库文件,将此目录下所有的so和.a文件都拷贝到 rootfs/lib 目录中:

cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/lib/ -d 

后面的“-d”表示拷贝符号链接,这里有个比较特殊的库文件:ld-linux-armhf.so.3,此库文件也是个符号链接,相当于 Windows 下的快捷方式。会链接到库 ld-2.19-2014.08-1-git.so 上,输入命令如下指令查看此文件详细信息:

ls ld-linux-armhf.so.3 -l
poYBAGIuAuKAciG5AAHiz4nlKaA107.png

ld-linux-armhf.so.3 后面有个“->” ,表示其是个软连接文件,链接到文件ld-2.19-2014.08-1-git.so,因为其是一个“快捷方式” ,因此大小只有 24B。但是,ld-linux-armhf.so.3不能作为符号链接,否则的话在根文件系统中执行程序无法执行!所以我们需要重新复制ld-linux- armhf.so.3,替换掉这个软链接。

先删除这个软连接文件:

rm ld-linux-armhf.so.3

然后重新进入到 /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm- linux-gnueabihf/libc/lib 目录中,重新拷贝ld-linux-armhf.so.3,命令如下:

cp ld-linux-armhf.so.3 /home/xxpcb/myTest/nfs/rootfs/lib/

拷贝完成以后再到 rootfs/lib 目录下查看ld-linux-armhf.so.3文件详细信息,此时ld-linux-armhf.so.3 已经不是软连接了,而是实实在在的一个库文件,而且文件大小为 724392B。

pYYBAGIuAuiAUWyFAAIBaYbRMmM039.png

继续进入如下目录中:

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
poYBAGIuAu-Aely8AAFXIcan8z0929.png

此目录下也有很多的的so和.a 库文件,我们将其也拷贝到 rootfs/lib 目录中,命令如下:

cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/lib/ -d 

rootfs/lib 目录的库文件就这些了,完成以后的rootfs/lib目录如图:

pYYBAGIuAvaAf7r7AAKq75mvV3w590.png

2.5.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/xxpcb/myTest/nfs/rootfs/usr/lib/ -d

完成以后的rootfs/usr/lib目录为:

pYYBAGIuAvyAJbb4AAF5fYVgKkM898.png

至此,根文件系统的库文件就全部添加好了,可以在rootfs目录下使用“du”命令来查看一下/lib和/usr/lib 这两个目录的大小:

du ./lib ./usr/lib/ -sh  
poYBAGIuAwSAfhY5AAC85qio4W0088.png

2.6 创建其他文件夹

在根文件系统中创建其他文件夹,如 dev、proc、mnt、sys、tmp 和 root 等,创建完后的效果:

poYBAGIuA2OAf33nAAEHNhz5jWw752.png

3 根文件系统初步测试

3.1 bootargs环境变量设置

使用NFS挂载的方式来测试上面创建好的根文件系统rootfs。

uboot里面的bootargs环境变量会设置root的值,需要将root的值改为NFS挂载,设置格式如为:

root=/dev/nfs nfsroot=[:][,] ip=::::::::

:服务器IP,存放根文件系统的Ubuntu的IP地址,比如我的192.168.5.105。

:根文件系统的存放路径,比如我的就是/home/xxpcb/myTest/nfs/rootfs。

:NFS 的其他可选选项,一般不设置。

:客户端IP ,开发板的IP地址,Linux内核启动以后就会使用此IP地址来配置开发板。我的为92.168.5.102。

:网关地址,我的就是 192.168.5.1。

:子网掩码,我的就是 255.255.255.0。

:客户机的名字,一般不设置,此值可以空着。

:设备名,也就是网卡名,一般是 eth0,eth1….,正点原子与野火的开发板均为ENET2为eth0,ENET1为eth1。这里我们使用ENET2,所以网卡名就是 eth0。

:自动配置,一般不使用,所以设置为 off。

:DNS0 服务器 IP 地址,不使用。

:DNS1 服务器 IP 地址,不使用。

根据上面的格式bootargs环境变量的root值如下:

root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off

启动开发板,串口连接开发板,进入uboot命令行模式,然后设置bootargs环境变量,命令如下:

setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off' 
saveenv  

设置好以后使用“boot”命令启动Linux内核

Linux内核的启动还是按照上一篇介绍的,使用tftp将zImage和设备树传输到开发板中运行

这里注意一下,因为此次测试,我将zImage和dtb文件移入了tftp目录中的nxp文件夹中,所以传输指令需要修改一下:

setenv bootcmd 'tftp 80800000 nxp/zImage; tftp 83000000 nxp/imx6ull-myboard.dtb; bootz 80800000 - 83000000' 
saveenv

然后就可以使用boot命令来进行tftp传输了。

3.2 NFS挂载错误与解决方法

3.2.1 错误提示

在使用boot命令来进行tftp传输了,启动内核时,出现了NFS根文件系统不能挂载的错误:

VFS: Unable to mount root fs via NFS, trying floppy.

VFS: Cannot open root device "nfs" or unknown-block(2,0): error -6
poYBAGIuA3eAEi-NAAHRT0Gn6AM139.png

3.2.2 无效的解决方法

先是尝试了多种方法,都不能解决问题,这些无效的方法包括:

尝试修改配置,将Linux System Utilities ->Support mounting NFS file选中(无效)

pYYBAGIuA4OAQC-uAAEY1ZqfbOE579.png

尝试将nfs目录的下的rootfs文件夹赋予777的权限(无效)

poYBAGIuA4mAAksHAABvDlOwypw069.png

尝试换用其它的串口软件(SecureCRT)来操作(无效)

3.2.3 有效的解决方法

最后,参考这篇博文:https://blog.csdn.net/InFoport/article/details/90317697

通过在bootargs添加中添加nfsvers=4,这个选项,就可以正常挂载nfs的文件系统了:

setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp,nfsvers=4 rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off' 
poYBAGIuA46AQvdIAADWUVDuFT0990.png

注:无效方法中的Linux System Utilities ->Support mounting NFS file,因开启后也不起作用,后续测试就将其改为默认的不勾选。

3.3 文件系统使用测试

按下回车键,就进入了文件系统,使用ls命令就可以看到了系统文件。

再使用touch命令来新建一个中文名称的文件,也是OK的。

pYYBAGIuA5SAQNaBAACjyeie_NM112.png

4 总结

本篇使用BusyBox来构建根文件系统,并通过NFS网络调试的方式实现根文件系统挂载测试,实测时解决了NFS根文件系统不能挂载的问题,最终根文件系统基本功能测试正常。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5068

    文章

    19008

    浏览量

    302971
  • Linux
    +关注

    关注

    87

    文章

    11219

    浏览量

    208872
  • 移植
    +关注

    关注

    1

    文章

    377

    浏览量

    28107
收藏 人收藏

    评论

    相关推荐

    【新品】i.MX6ULL工业嵌入式核心板!NXP低功耗MPU,LCD显示

    核心板新品上市ECK20-6Y2XA系列核心板是亿佰特基于NXPCortex-A7内核i.MX6ULL处理器精心设计的,采用邮票孔连接的低成本、低功耗、高性价比、高可靠性的嵌入式核心板。可广泛应用于工业控制、HMI、IoT等领域
    的头像 发表于 11-15 01:04 84次阅读
    【新品】<b class='flag-5'>i.MX6ULL</b>工业<b class='flag-5'>嵌入式</b>核心板!NXP低功耗MPU,LCD显示

    【北京迅为】i.mx8mm嵌入式linux开发指南第四篇 嵌入式Linux系统移植篇第六十九章uboot移植

    【北京迅为】i.mx8mm嵌入式linux开发指南第四篇 嵌入式Linux
    的头像 发表于 10-22 14:46 502次阅读
    【北京迅为】<b class='flag-5'>i.mx</b>8mm<b class='flag-5'>嵌入式</b><b class='flag-5'>linux</b><b class='flag-5'>开发</b>指南第四篇 <b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b><b class='flag-5'>系统</b>移植篇第六十九章uboot移植

    Linux文件系统的挂载过程

    Linux文件系统(rootfs)是Linux系统中所有其他文件系统和目录的起点,它是内核启动
    的头像 发表于 10-05 16:50 262次阅读

    如何构建Linux文件系统

    构建Linux文件系统是一个涉及多个步骤和概念的过程,它对于Linux系统的启动和运行至关重要
    的头像 发表于 10-05 16:47 227次阅读

    嵌入式linux开发的基本步骤有哪些?

    嵌入式Linux开发是一个复杂的过程,涉及到硬件选择、操作系统移植、驱动开发、应用程序开发等多个
    的头像 发表于 09-02 09:11 380次阅读

    嵌入式linux开发板怎么操作

    嵌入式Linux开发板是一种基于Linux操作系统嵌入式
    的头像 发表于 09-02 09:09 316次阅读

    嵌入式linux开发板芯片的工作原理

    嵌入式Linux开发板是一种基于Linux操作系统嵌入式
    的头像 发表于 09-02 09:07 319次阅读

    STM32MP157D使用buildroot生成文件系统时就无法正常显示,为什么?

    我在使用最新OpenSTLinux(5.1.0)Linux版本:6.1.28,使用官方的文件系统(st-image-weston-openstlinux-weston-stm32mp1.ext
    发表于 07-26 06:21

    浅析在NXP I.MX6ULL+Linux平台下进行WM8960音频芯片移植的过程

    本文详细记录在NXP I.MX6ULL+Linux平台下进行WM8960音频芯片移植的过程,其他平台操作方法类似,希望为大家提供帮助。
    的头像 发表于 05-17 11:33 1177次阅读
    浅析在NXP <b class='flag-5'>I.MX6ULL+Linux</b>平台下进行WM8960音频芯片移植的过程

    基于飞凌嵌入式i.MX6ULL核心板的电梯智能物联网关方案

    使用飞凌嵌入式FETMX6ULL-S核心板作为智能电梯物联网关的主控平台,为智能电梯的变革提供了强有力的技术支持。
    的头像 发表于 03-22 10:45 1385次阅读
    基于飞凌<b class='flag-5'>嵌入式</b><b class='flag-5'>i.MX6ULL</b>核心板的电梯智能物联网关方案

    嵌入式SD NAND】基于FATFS/Littlefs文件系统的日志框架实现

    文章目录【嵌入式】基于FATFS/Littlefs文件系统的日志框架实现1.概述2.设计概要3.设计实现3.1初始化`init`3.2日志写入`write`3.3日志读取`read`3.4注销
    的头像 发表于 03-14 18:12 1122次阅读
    【<b class='flag-5'>嵌入式</b>SD NAND】基于FATFS/Littlefs<b class='flag-5'>文件系统</b>的日志框架实现

    嵌入式学习-ElfBoard ELF 1-gpio模拟i2c的方法

    /linux-4.1.15-elf1$ make zImage 二、设备树修改设备树路径:linux-4.1.15-elf1/arch/arm/boot/dts/imx6ull-elf1-emmc.dts(1)将
    发表于 02-22 15:17

    嵌入式软件开发应该掌握哪些知识?

    知识点学习 熟悉 Linux 的基本使用对于嵌入式软件开发至关重要。包括文件系统的管理、用户权限的控制、软件包管理等。嵌入式开发人员需要能够
    发表于 02-19 11:23

    嵌入式学习——ElfBoard ELF1板卡 之文件系统的介绍

    文件系统是一样的,只是嵌入式Linux文件系统根据产品功能进行过裁剪,在内容多少和体积大小上不同。进行嵌入式
    发表于 11-24 10:02

    i.MX6ULL——ElfBoard ELF1板卡 之文件系统目录的介绍

    文件系统是一样的,只是嵌入式Linux文件系统根据产品功能进行过裁剪,在内容多少和体积大小上不同。进行嵌入式
    发表于 11-24 09:59