查看: 1267|回复: 1

[分享] 【经验分享】i.MX6ULL开发:嵌入式Linux开发4-根文件系统构建

[复制链接]
  • TA的每日心情
    开心
    2020-12-18 12:56
  • 签到天数: 55 天

    [LV.5]常住居民I

    75

    主题

    225

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    1630
    最后登录
    2024-4-25
    发表于 2022-8-16 10:45:14 | 显示全部楼层 |阅读模式
    前面几篇介绍了uboot的移植内核的移植,本篇进行根文件系统的构建,这是Linux移植三大组成部分的最后一步,根文件系统构建好后,就构成了一个基础的、可以运行的嵌入式Linux最小系统。
    1 根文件系统简介
    Linux的根文件系统一般也叫做 rootfs,Linux的根文件系统更像是一个文件夹或者叫做目录,在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文件,这些文件是Linux运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。
    根文件系统的这个“根”字就说明了这个文件系统的重要性,它是其他文件系统的根,没有这个“根” ,其他的文件系统或者软件就别想工作。比如我们常用的 ls、mv、ifconfig 等命令其实就是一个个小软件,只是这些软件没有图形界面,而且需要输入命令来运行。这些小软件就保存在根文件系统中。
    在构建根文件系统之前,先来看一下根文件系统里面都有些什么内容,根文件系统的目录名字为‘/’ ,就是一个斜杠:
    图片 1.png
    根文件系统的各个文件夹的作用如下:
    图片 2.png
    2 BusyBox构建根文件系统2.1 BusyBox简介
    BusyBox是一个集成了大量的Linux命令(如ls、mv、ifconfig 等命令)和工具的软件。借助BusyBox,进行配置和编译,就可以方便的构建一个嵌入Linux平台所需要的根文件系统。
    课程BusyBox官网https://busybox.net/下载源码,如下图。
    图片 3.png
    左侧的“Get BusyBox”栏有一行“Download Source” ,点击“Download Source”即可打开 BusyBox 的下载页。
    图片 4.png
    目前最新的 BusyBox 版本是1.33.1,但这里使用正点原子提供的1.29.0版本的BusyBox(busybox-1.29.0.tar.bz2)
    2.2 搭建NFS服务
    一般在Linux驱动开发的时候都是通过NFS挂载根文件系统的,当调试好之后再将根文件系统烧写到 EMMC或者NAND中,因此需要先在ubuntu虚拟机中构建NFS服务:
    1. sudo apt-get install nfs-kernel-server rpcbind
    复制代码
    等待安装完成,在合适的地方新建一个名为“nfs”的文件夹,供NFS服务器使用。
    如我的创建目录为:/home/xxpcb/myTest/nfs
    在使用NFS之前,还需要先配置NFS,修改配置文件/etc/exports,在后面添加如下所示内容:
    1. /home/xxpcb/myTest/nfs *(rw,sync,no_root_squash)
    复制代码
    图片 5.png
    最后重启NFS服务即可:
    1. <span style="font-family: Consolas; color: rgb(221, 74, 104); font-size: 7pt; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">sudo</span><span class="16" style="font-family: Consolas; color: rgb(0, 0, 0); font-size: 7pt; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;"> /etc/init.d/nfs-kernel-server restart</span>
    复制代码
    正常情况会出现如下图,表示设置成功:
    图片 6.png
    注:我第一次设置时,文件路径中的一个大小写字母搞错了,导致重启NFS时提示失败(如下图),所以在设置时要注意细节!
    图片 7.png
    2.3 修改配置BusyBox
    nfs服务器目录中创建一个名为rootfs的子目录,用来存放我们的根文件系统。
    将busybox-1.29.0.tar.bz2发送到Ubuntu中的合适位置(我存放在 /home/xxpcb/myTest/imx6ull/dts)并解压:
    1. tar -vxjf busybox-1.29.0.tar.bz2
    复制代码
    解压后的文件如下:
    图片 8.png
    2.3.1 修改Makefile添加编译器
    注:这一步可以不修改,这里修改Makefile的目的是为了在编译时,可以不用在指定编译器的架构,从而可以缩短手动输入指令的长度。但我此次测试时,修改Makefile后,输入make指令的命令进行编译时,不指定编译器,还是会提示编译器找不到之类的问题。所以,此次的测试,我就没有修改这个Makefile。
    如果坚持要修改Makefile,就是修改如下的地方,指定编译器与架构(本篇进行实验时没有修改)。
    图片 9.png
    2.3.2 busybox中文字符支持
    现在如果直接编译busybox的,在使用串口工具的时候是不支持中文显示的,中文字符会显示为“?” 。可以通过busybox源码,来取消 busybox对中文显示的限制。
    打开文件busybox-1.29.0/libbb/printable_string.c,找到函数printable_string,吧某些程序注释掉,修改后的函数内容如下:
    图片 10.png
    主要就是禁止字符大于0X7F以后 break 和输出‘?’
    接着打开文件busybox-1.29.0/libbb/unicode.c,修改如下内容:
    图片 11.png
    2.3.3 配置busybox
    有以下几种配置选项:
    defconfig:缺省配置,也就是默认配置选项
    allyesconfi:全选配置,也就是选中 busybox 的所有功能
    allnoconfig:最小配置
    一般使用默认配置即可,因此使用如下命令先使用默认配置来配置一下 busybox:
    1. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
    复制代码
    图片 12.png
    busybox也支持图形化配置,通过图形化配置我们可以进一步选择自己想要的功能,输入如下命令打开图形化配置界面:
    1. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
    复制代码
    图片 13.png
    (1) 设置Settings -> Build static binary (no shared libs)
    选项“Build static binary (no shared libs)”用来决定是静态编译还是动态编译,静态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库文件,但是编译出来的 busybox 会小很多。这里我们不使用静态编译,所以保持默认不选即可。
    图片 14.png
    (2) 设置Settings -> vi-style line editing commands
    这个要勾选,通过按键“y”实现勾选,使得方括号内出现星号
    图片 15.png
    (3) 配置Linux Module Utilities -> Simplified modutils
    默认会选中“Simplified modutils” ,这里我们要取消勾选 使用键盘上的“n”键取消方括号中的星号。
    图片 16.png
    (4) 配置Linux System Utilities  -> mdev (16 kb)  
    确保下面的全部选中,默认都是选中
    图片 17.png
    (5) 设置Settings -> Support Unicode  
    要将默认没有勾选的Check $LC_ALL项选中
    图片 18.png
    最后按两下ESC退出设置,并选择YES保持存
    2.4 编译busybox构建根文件系统
    输入如下指令进行编译:
    1. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
    2. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install CONFIG_PREFIX=/home/xxpcb/myTest/nfs/rootfs
    复制代码
    编译完成以后, busybox的所有工具和文件就会被安装到rootfs目录中,如下图:
    图片 19.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/”目录中,进入对应的目录:
    1. cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
    复制代码
    图片 20.png
    此目录下有很多的so和.a 文件,这些就是库文件,将此目录下所有的so和.a文件都拷贝到 rootfs/lib 目录中:
    1. 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 上,输入命令如下指令查看此文件详细信息:
    1. ls ld-linux-armhf.so.3 -l
    复制代码
    图片 21.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,替换掉这个软链接。
    先删除这个软连接文件:
    1. 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,命令如下:
    1. 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。
    图片 22.png
    继续进入如下目录中:
    1. cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
    复制代码
    图片 23.png
    此目录下也有很多的的so和.a 库文件,我们将其也拷贝到 rootfs/lib 目录中,命令如下:
    1. cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/lib/ -d
    复制代码
    rootfs/lib 目录的库文件就这些了,完成以后的rootfs/lib目录如图:
    图片 24.png
    2.5.2 向rootfs/usr/lib中添加
    在rootfs/usr目录下创建一个名为lib的目录, 将如下目录中的库文件拷贝到rootfs/usr/lib目录下:
    1. /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目录中:
    1. cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/usr/lib/ -d
    复制代码
    完成以后的rootfs/usr/lib目录为:
    图片 26.png
    2.6 创建其他文件夹
    在根文件系统中创建其他文件夹,如 dev、proc、mnt、sys、tmp 和 root 等,创建完后的效果:
    图片 27.png
    3 根文件系统初步测试3.1 bootargs环境变量设置
    使用NFS挂载的方式来测试上面创建好的根文件系统rootfs。
    uboot里面的bootargs环境变量会设置root的值,需要将root的值改为NFS挂载,设置格式如为:
    1. 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>
    复制代码
    <server-ip>:服务器IP,存放根文件系统的Ubuntu的IP地址,比如我的192.168.5.105。
    <root-dir> :根文件系统的存放路径,比如我的就是/home/xxpcb/myTest/nfs/rootfs。
    <nfs-options>NFS 的其他可选选项,一般不设置。
    <client-ip> :客户端IP ,开发板的IP地址,Linux内核启动以后就会使用此IP地址来配置开发板。我的为92.168.5.102。
    <gw-ip> :网关地址,我的就是 192.168.5.1。
    <netmask>:子网掩码,我的就是 255.255.255.0。
    <hostname>:客户机的名字,一般不设置,此值可以空着。
    <device> :设备名,也就是网卡名,一般是 eth0,eth1….,正点原子与野火的开发板均为ENET2为eth0,ENET1为eth1。这里我们使用ENET2,所以网卡名就是 eth0。
    <autoconf> :自动配置,一般不使用,所以设置为 off。
    <dns0-ip>DNS0 服务器 IP 地址,不使用。
    <dns1-ip> :DNS1 服务器 IP 地址,不使用。
    根据上面的格式bootargs环境变量的root值如下:
    1. 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环境变量,命令如下:
    1. 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文件夹中,所以传输指令需要修改一下:
    1. 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
    图片 28.png
    3.2.2 无效的解决方法
    先是尝试了多种方法,都不能解决问题,这些无效的方法包括:
    ·
    尝试修改配置,将Linux System Utilities  ->Support mounting NFS file选中(无效)
    图片 29.png
    尝试将nfs目录的下的rootfs文件夹赋予777的权限(无效)
    图片 30.png
    尝试换用其它的串口软件(SecureCRT)来操作(无效)
    3.2.3 有效的解决方法
    最后,参考这篇博文:https://blog.csdn.net/InFoport/article/details/90317697
    通过在bootargs添加中添加nfsvers=4,这个选项,就可以正常挂载nfs的文件系统了:
    1. 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'
    复制代码
    图片 31.png
    注:无效方法中的Linux System Utilities  ->Support mounting NFS file,因开启后也不起作用,后续测试就将其改为默认的不勾选。
    3.3 文件系统使用测试
    按下回车键,就进入了文件系统,使用ls命令就可以看到了系统文件。
    再使用touch命令来新建一个中文名称的文件,也是OK的。
    图片 32.png

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

    图片 25.png
    签到
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    0

    新手上路

    Rank: 1

    积分
    38
    最后登录
    2022-8-22
    发表于 2022-8-16 11:15:38 | 显示全部楼层
    请教一下,如果直接使用ubuntu core文件系统,后面想用Qt做界面,怎么移植Qt那些库呢?
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-25 22:36 , Processed in 0.119193 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表