imx6ull移植Linux系统第三篇——根文件系统的构建

imx6ull移植Linux系统第三篇——根文件系统的构建

花了大概两周的时间,把Linux的移植认真学了一遍,期间踩了不少坑,花费了不少时间去解决各种奇奇怪怪的问题,最终完成了uboot、系统镜像、设备树以及根文件系统的制作,并最终下载到开发板上运行。这里想对这两周的学习内容进行一个总结,因为后期会有其他的学习安排,系统移植是一些经验和方法的掌握,如果长时间不去用,时间久了肯定会忘,希望这里写的总结会对后期的移植工作给出一些方法上的参考。


提示:本系列文档共分四篇:U-Boot的移植、Linux内核的移植、根文件系统的构建、系统烧写,本文为第三篇根文件系统的构建。



前言

  Linux的根文件系统有很多种,笔者尝试过移植busybox、buildroot、ubuntu-base这三种根文件系统。我最终日常使用的还是ubuntu-base根文件系统,因为前两个很多功能不是很完善,最主要是不支持pip指令,使用起来不是很方便,而Ubuntu系统功能较为完善,另外对它的文件结构较为熟悉,用起来比较顺手。但是对于初学者来说,练习一下busybox和buildroot的移植还是大有裨益的,因为它们的文件系统比较简单,可以帮助我们熟悉Linux系统,不妨尝试过后再去接触ubuntu-base根文件系统。


一、什么是根文件系统

  根文件系统是内核启动时所挂载的第一个文件系统,内核启动后会从根文件系统读取一些初始化脚本来执行,比如rcS,inittab 等。根文件系统下有很多个根目录和子目录,这些目录里存放了库、常用的软件、命令、设备文件、配置文件等,Linux内核正常运行必须要有根文件系统。关于根文件系统的结构就不单独介绍了,我们直接边做边看。

二、构建自己的根文件系统

2.1 下载安装BusyBox工具

  到目前为止,我们所做的工作都是站在巨人的肩膀上,因为Linux是一个复杂的操作系统,我们从0开始构建根文件系统也几乎是不可能的,好在有做好的现成的工具供我们使用,这就是BusyBox。我们可以去BusyBox官网下载,也可以从正点原子的资料中找到,名字叫做 busybox-1.29.0.tar.bz2,发送到Ubuntu下新建的rootfs目录,用命令 tar -vxjf busybox-1.29.0.tar.bz2 解压。

2.2 修改Makefile

  打开busybox的顶层Makefile,修改如下:

CROSS_COMPILE ?= /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
......
ARCH ?= arm

  这里就是添加交叉编译器和架构,注意添加的交叉编译器使用了绝对路径,只要路径没问题,编译肯定不会出错。

2.3 busubox修改中文支持

  现在的busybox对中文字符做了限制,要想显示中文字符,就必须修改busybox源码,这里不做介绍,过程稍繁琐但方法很简单,对照正点原子的教程修改即可。

2.4 配置busybox

  可以用命令 make defconfig 默认配置,也可以用图形化配置,图文过多,不做介绍,详情见正点原子教程。

2.5 编译busybox

  配置好的busybox经过编译就能得到rootfs文件了,我们输入命令(root模式下):

make install CONFIG_PREFIX=/home/x-ice/linux/rootfs

  CONFIG_PREFIX是指定编译结果的存放目录,也就是说编译结果不像之前保存在当前目录下。这里我指定了一个创建好的/home/x-ice/linux/rootfs目录,编译完成后在该目录下可以看到busybox自动创建的文件,但是这时的根文件系统还不完善,我们需要做一些添加和修改的工作。

2.6 向根目录系统添加lib库

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

  Linux的应用程序需要调用动态库,所以这里我们给 rootfs 添加动态库(静态库太大了),但动态库文件从哪来呢?前面我们在Ubuntu的目录 /usr/local/arm 下安装了交叉编译器,交叉编译器里面有很多的库文件,虽然有些我们可能用不上,但是全复制过来肯定不会出错,等到我们以后有能力了再回过头来做裁剪。
  我们在rootfs中创建一个名为 “lib” 的文件夹,然后进入目录 /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linuxgnueabihf/libc/lib,将该目录下的所有so和.a文件都拷贝到目录 rootfs/lib 下,拷贝命令为:

cp *so* *.a /home/zuozhongkai/linux/nfs/rootfs/lib/ -d

  但是这里会拷贝一个特殊的库文件:ld-linux-armhf.so.3,此文件是连链接符号,相当于一个“快捷方式”,我们想把它换成“本尊”,那么先将rootfs/lib 中的 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/armlinux-gnueabihf/libc/lib 目录,拷贝 ld-linux-armhf.so.3:

cp ld-linux-armhf.so.3 /home/x-ice/linux/rootfs/lib/

  接下来我们还要复制一些其他的库文件,先进到目录 /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib 下,还是复制那些so和.a库文件:

cp *so* *.a /home/zuozhongkai/linux/nfs/rootfs/lib/ -d

  到此rootfs/lib目录的库文件就制作完了,我们再去完善其他地方。

2.6.2 向 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/zuozhongkai/linux/nfs/rootfs/usr/lib/ -d

  这样根文件系统的库文件就制作完了,在rootfs目录下用 du ./lib ./usr/lib/ -sh 命令查看库文件大小,结果应该是57M和67M大小。

2.7 创建其他文件夹

  在根文件系统中创建其他文件夹,如dev、proc、mnt、sys、tmp 和 root 等,这样根文件系统的结构就基本做好了。

2.8 完善根文件系统

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

  rcS是Linux内核启动以后执行的一个shell脚本,它规定了需要执行哪些服务,也可以把我们要执行的事情放到rcS脚本中执行,实现开机自启动的效果。我们在rootfs中创建 /etc/init.d/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

  然后用chmod赋予rcS脚本可执行权限。

2.8.2 创建/etc/fstab 文件

  在 rootfs 中创建 /etc/fstab 文件,fstab 在 Linux 开机以后自动配置哪些需要自动挂载的分区,输入以下内容:

#<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

2.8.3 创建/etc/inittab 文件

  创建一个 /etc/inittab,输入如下内容:

#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

  至此根文件系统就制作好了,为了便于调试,可以通过NFS服务器挂在到开发板。

三、烧写我们自制的系统

  给imx6ull烧写系统由两个方法,一种是通过OTG数据线直刷,另外一种是在Ubuntu系统下通过SD卡刷机。
  法一使用OTG直接在Windows下,使用mfgtool刷到开发板的EMMC中,主要包含两个阶段:1.将firmware文件夹下的uboot、Linux kernel和.dtb文件下载到SOC的DDR中,目的是在DDR中启动Linux系统,为下一步烧写做准备;2.此时 Linux 系统已经运行起来了,系统运行起来以后就可以很方便的完成对 EMMC 的格式化、分区等操作。EMMC 分区建立好以后就可以从 files 中读取要烧写的uboot、linux kernel、.dtb和 rootfs 这 4 个文件,然后将其烧写到 EMMC 中。
  法二需要将mfgtool里面的file文件夹通过共享文件夹复制到Ubuntu下,然后将一张格式化好的内存卡接入Ubuntu,执行file文件夹里的imx6mksdboot.sh脚本(用–help查看相应的参数),等待SD卡烧写完成,然后我们还需要将file文件拷贝到SD卡的/home/root下。将SD卡插入开发板,选择SD卡启动,这时系统会在SD卡上运行,我们打开刚才拷贝到SD卡的file文件,运行imx6mkemmcboot.sh脚本,将系统烧写到EMMC上。
  其实法一和法二的原理是一样的,都是让系统先运行起来,再固化到EMMC上。
  另外需要记住的是,fileware文件夹存放uboot、Linux kernel和.dtb文件,是为了第一步让DDR运行起来,file文件夹存放uboot、linux kernel、.dtb和 rootfs,是最终需要固化到EMMC上的,当然还有一些其他的引导程序,若我们需要去烧写自己定制的系统,那就需要用我们自己制作的uboot、linux kernel、.dtb和 rootfs去替换mfgtool里fileware和file文件夹下的文件即可。
  注:这里需要对rootfs文件进行打包压缩,命令为:

cd rootfs/
tar -vcjf rootfs.tar.bz2 *

  使用OTG的方式需要几个文件重命名,放到修改过的mfgtool文件中去,重命名后的文件为:
Image File


四、部分问题汇总

4.1 关于从NFS中启动根文件失败的解决方法

  前面在做Linux移植的时候,关于NFS启动根文件的部分一直没有成功,由于我在移植完根文件以后,直接将根文件烧写到开发板上了,所以这部分的问题我就忽略过去了。直到最近,我想在自己移植的系统上测试内核开发的程序时,由于手头上没有路由器,我的开发板和电脑一直是通过交换机来通信的,并且正点原子的开发板没有板载WiFi,这就导致我的开发板无法联网,也就不能下载NFS客户端了,现将解决方法写下来:
  现象:设置好uboot中的IP信息和bootargs,在uboot中可以ping通网络,说明网络连接没问题;启动开发板,发现Linux内核启动报错,会在最后卡住,提示eth0有问题,然后打印一堆信息:
在这里插入图片描述
  解决:确定网络可以ping通,bootargs配置没问题,Ubuntu的NFS配置正确,那么这种情况就是Ubuntu版本的问题了,我们需要按照下图修改Ubuntu下的/etcdefault/nfs-kernel-server文件,然后重启NFS服务器,再重试一下看能不能挂载上,基本就成功了。
在这里插入图片描述

4.2 关于编译 Buildroot 时出现 you should not run configure as root (set FORCE_UNSAFE_CONFIGURE=1 in environment to bypass this check)

  需要在编译之前,执行:

export FORCE_UNSAFE_CONFIGURE=1

4.3 关于ubuntu-base根文件移植的问题

4.3.1 关于根文件运行BUG

  根文件移植完以后,挂载到NFS上进行测试,结果出现一分半的倒计时等待,随后卡死:
在这里插入图片描述
解决方法:

  1. 在/etc/init/ 增加 ttymxc0.conf文件,输入以下内容:
start on stopped rc RUNLEVEL=[2345] and container CONTAINER=lxc
stop on runlevel [!2345]
respawn
exec /sbin/getty -L 115200 ttymxc0 vt100
  1. 建立一个软连接
ln -s /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@ttymxc0.service

  修改完以后,重新挂载、重启,完美解决。

4.3.2 普通用户无法进入root模式

  先按正点原子教程修改,不行再按下面方法修改:
  新安装的根文件是无法在普通用户下进入root模式的,根据正点原子教程需要修改某配置文件,但是我尝试过后发现不起作用,于是采用第二种方法:

  1. 以root模式登陆
  2. 执行chown root:root /usr/bin/sudo
  3. 执行chmod 4755 /usr/bin/sudo
  4. reboot后普通用户就又可以用sudo了;

4.3.3 Ubuntu 16.04开机A start job is running for Raise network interface(5min 4s)解决方法

  进入系统后修改文件 /etc/systemd/system/network-online.target.wants/networking.service

sudo vim /etc/systemd/system/network-online.target.wants/networking.service

  将里面的 TimeoutStartSec=5min 修改为TimeoutStartSec=2sec,再重启系统即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值