2.构建最小根文件系统(踩坑记录)

搭建一个用于驱动开发的最小根文件系统

配置编译busybox

busybox 官方网站:http://www.busybox.net/
我直接下载了最新的版本

1.解压
2.修改Makefile

找到CROSS_COMPILE变量,吧自己的编译器前缀赋值

CROSS_COMPILE ?= arm-linux-

我看ARCH变量不需要设置了,代码中已经根据CROSS_COMPILE自动推断平台了,如果你的编译器前缀不带有平台标志(arm)那么需要自己设置下

3.配置

busyboy默认安装目录为_install,直接修改为自己的rootfs目录

make menuconfig
  • Settings—>

    • Build Options—>
      • [*]Build BusyBox as a static binary(no shared libs)
    • Library Tuning—>
      • [*]vi-style line editing commands
      • [*]Fancy shell prompts
      • — Installation Options (“make install” behavior)
        What kind of applet links to install (as hard-links)
        • —> (/home/minicoco/disk1/Dev/nanopi/rootfs) Destination path for ‘make install’
          直接将自己的rootfs配置到安装目录
  • Linux Module Utilities—>

    • [ ]Simplified modutils
    • [*]depmod
    • [*]insmod
    • [*]lsmod
    • [*] Pretty output
    • [*] modinfo
    • [*]modprobe
    • [*] Blacklist support
    • [*]rmmod
  • Linux System Utilities—>

    • [*]mdev
    • [*]Support /etc/mdev.conf
    • [*]Support subdirs/symlinks
    • [*]Support regular expressions substitutions when renaming dev
    • [*]Support command execution at device addition/removal
    • [*]Support loading of firmwares
4.编译
make -j16

编译没有遇到错误

5.安装
make install

安装步骤实际上就是拷贝编译结果到指定目录(rootfs)

6.创建常用文件夹
cd rootfs
mkdir dev mnt proc var tmp sys root lib

拷贝链接库

1.在rootfs目录下创建lib目录
mkdir lib
2.拷贝动态库

找到自己编译工具的动态连接库,一般在编译工具的lib文件夹下面

cp ~/disk1/Dev/nanopi/prebuilts/gcc-x64/opt/FriendlyARM/toolchain/4.9.3/arm-cortexa9-linux-gnueabihf/lib* lib/
3.使用strip工具去掉库中符号信息

动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在传统的嵌入式系统中flash空间是有限的,为了节省空间常常把这些符号信息去掉。这样节省空间并且不影响运行。进入rootfs/lib目录,执行命令:

arm-none-linux-gnueabi-strip *so*

实际操作后发现库文件由3.8M变成了3.0M,节省了0.8M的空间。

配置系统

1. 添加inittab文件到etc文件夹
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a –r
2. inittab格式解析
init进程启动后最开始就是读取inittab中的指令执行
inittab 由文本组成。
  • .# 注释
  • .: 分隔符,每行代表一个独立的含义 ,分隔开各个部分。
  • ./ 目录
  • .inittab内容是以行为单位,行与行之间没有关联
  • .每一行的配置项都是由3个冒号分隔开的4个配置值共同确定。这四个配置值就是id:runlevels:action:process。值得注意 得是有些配置值可以空缺,空缺后冒号不能空缺,所以有时候会看到连续2个冒号。
  • .每一行的配置项中4个配置值中最重要的是action和process,action是一个条件/状态,process是一个可被执行的程序的pathname。合起来的意思就是:当满足action的条件时就会执行process这个程序。理解inittab的关键就是明白“当满action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。

sysinit 指定的进程在访问控制台之前执行,这样的条目仅用于对某些设备的初始化,目的是为了使init在这样的设备上向用户提问有关运行级别的问题,init需要等待进程运行结束后才继续

respawn 如果process字段指定的进程不存在,就启动该进程,init不会等待处理结束,而是继续扫描inittab文件。当该进程被终止时,init将重新启动它。如果相应的进程已经存在,init就忽略该条目并继续扫描inittab文件

askfirst 类似respawn,主要用途是减少系统上执行的终端应用程序的数量。它将会促使init在控制台上显示“Please press Enter to active this console”的信息,并在重新启动进程之前等待用户按下“enter”键
wait 告诉init必须等到相应的进程执行完成之后才能继续执行

once 启动进程,不会等待处理结束,而是继续处理下一条条目。当该进程被终止时,init不会重新启动它。从一个运行级别进入另一个运行级别时,如果相应的进程仍 在运行,init就不会重新启动该进程

ctratldel 当按下Ctrl+Alt+Delete组合键时,执行相应的进程

shutdown 当系统关机时,执行相应的进程

restart 当init重新启动时,执行相应的进程,通常此处所执行的进程就是init本身

boot 只在系统启动时,init才处理这条条目,启动相应的进程,并不等待处理结束就去处理下一条条目。当这样的进程终止时,也不会重新启动它

bootwait 系统启动后,当第一次从单用户模式进入多用户模式时才处理该条目,init启动这样的进程,并且等待其处理结束才处理下一条条目,当该进程被终止时,也不重新启动它。

off 如果相应的进程正在运行,那么就发出一个警告信号,等待数秒后,再发出信号SIGKILL强制终止该进程。如果相应的进程不存在就忽略该条目

initdefault 指定一个默认的运行级别,如果指定了多个运行级别,其中最大的数字将是默认的运行级别。如果inittab文件没有包含该条目,在系统启动时会请求用户为其指定一个默认的运行级别

powerwait 当初接接到断电的信号时,处理指定的进程,并且等到处理结束后才去检查其他的条目

powerfail 当init接到断电的信 时,处理指定的进程,但是不等待该进程处理结束。

3. 添加rcS文件

rcS文件放到etc/init.d文件夹中,是一个普通的sh脚本,做最小系统先不管里面的内容

mkdir init.d
nano init.d/rcS
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
 
runlevel=S
prevlevel=N
 
umask 022
 
export PATH runlevel prevlevel
 
mount -a
 
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
 
/bin/hostname -F /etc/sysconfig/HOSTNAME
ifconfig eth0 192.168.0.99

安装qemu

1. 安装qemu
sudo apt-get install qemu-user-static
2. 拷贝运行环境到rootfs
sudo cp /usr/bin/qemu-arm-static usr/bin/
sudo cp /usr/bin/qemu-aarch64-static usr/bin/
3. 在rootfs外面添加挂载脚本:mount-rootfs.sh
dir=rootfs/
sudo mount -t proc /proc ${dir}proc
sudo mount -t sysfs /sys ${dir}sys    
sudo mount -o bind /dev ${dir}dev
sudo mount -o bind /run ${dir}run 
sudo mount --bind / ${dir}host
sudo chroot ${dir} /bin/sh
4. 添加卸载脚本:umount-rootfs.sh
dir=rootfs/
sudo umount ${dir}proc
sudo umount ${dir}sys    
sudo umount ${dir}dev
sudo umount ${dir}run 
sudo umount ${dir}host
5.chroot进去先爽一把
sudo ./mount-rootfs.sh

一把过
在这里插入图片描述

nfs远程挂载

nfs配置可见我上一篇文章

1.重启开发板

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章