嵌入式 Linux 开发 6:定制根文件系统

简介根文件系统

根文件系统是 kernel 挂载的第 1 个文件系统,挂载的位置是文件系统层次结构的顶端,表示为 /
Linux 要求根文件系统中包含应用程序和工具软件,通过它们来引导系统,初始化系统服务,加载设备驱动程序和挂载额外的文件系统。

从零开始构建根文件系统是一个艰巨的任务,为了专注【将产品尽快出货】这个头等目标,使用厂商提供的根文件系统可以节省大量的时间和精力。
如果厂商提供的根文件系统尺寸合适,包含了设备必需的组件,特别是 C 程序库(常见为 uClibc)。
最佳的方法是建立应用程序,将其复制到现在的根文件系统,修改启动脚本,并重建根文件系统的二进制镜像。

尽管有 OpenEmbedded Buildroot LTIB 等构建 Linux 发布版工具,然而它们的学习曲线大致与【自行构建 Linux 系统】相当。
后者学习到的经验更容易应用于 Linux 的其它领域,这包括:交叉编译器,内核,根文件系统,部署 MTD 镜像。

根文件系统顶层目录

目录 内容
bin 用户和系统管理员必备的二进制文件
sbin 系统管理员必备的二进制文件
usr 大量应用程序和文件
dev 设备文件
etc 系统配置和启动文件
home 用户主目录
lib 程序库和内核模块
proc 描述内核与进程信息的虚拟文件系统
sys 描述总线/设备/驱动程序的虚拟文件系统
tmp 临时文件
var 系统日志和临时配置文件

小窍门
在嵌入式 Linux 系统中 var 一般是软链接指向 tmp@SDRAM 这样,避免 FLASH 耗损和提高 IO 效率。
先进入 var 目录,再创建子目录如 ln -s ../tmp ./log 这是相对路径 ../tmp 而不是绝对路径 /tmp(在 NFS 场景下这是开发主机目录)

烧录文件系统

定制根文件系统流程

  • 根据应用需求选择文件系统类型,请链接Linux 文件系统类型
  • 配置 kernel 支持该文件系统
  • 将数据(文件和目录)转换成所选文件系统格式的镜像文件
  • 将镜像文件烧录到目标系统上的 MTD 储存设备
  • 配置 u-boot 通过命令行参数使 kernel 启动 rootfs

定制 yaffs2 和 squashfs

配置 kernel 支持 yaffs2 和 squashfs
File systems--->Miscellaneous filesystems--->yaffs2 file system support:Autoselect yaffs2 format:Enable yaffs2 xattr support

配置 kernel 支持 squashfs
File systems--->Miscellaneous filesystems--->squashed file system support:Include support for LZO compressed file systems

生成 yaffs2 镜像文件
mkyaffs2 $SOURCE $IMAGE --inband-tags -p 2048

生成 squashfs 镜像文件
mksquashfs $SOURCE $IMAGE -comp lzo -no-xattrs

配置 u-boot 通过命令行参数使 kernel 启动 yaffs2 根文件系统
bootargs=noinitrd root=/dev/mtdblock2 rootfstype=yaffs2 rootflags=inband-tags console=ttyS0 rdinit=/sbin/init mem=64M mtdparts=nand0:2M(u-boot),20M(kernel),40M(rootfs),2M(config),-(log) ignore_loglevel

配置 u-boot 通过命令行参数使 kernel 启动 squashfs 根文件系统
bootargs=noinitrd root=/dev/mtdblock2 rootfstype=squashfs console=ttyS0 rdinit=/sbin/init mem=64M mtdparts=nand0:2M(u-boot),20M(kernel),40M(rootfs),2M(config),-(log) ignore_loglevel

经典的文件系统布局

下图是一个使用了 Flash 芯片的嵌入式 Linux 系统典型布局。

  • 具有系统软件的根文件系统被放在一个只读,经压缩的 SquashFS 文件系统中
  • 配置文件被储存在不同分区上一个可供读写的 YAFFS2 文件系统中
  • 临时文件被储存在使用 TmpFS 的 RAM 中

+-----------+
| SqushFS  |
| 只读压缩  |
| 根文件系统 |
+-----------+  Flash
| YAFFS2   |
| 可读可写  |
| 配置文件  |
+-----------+
+-----------+
| TmpFS   |
| 可读可写  |  RAM
| 临时数据  |
+-----------+

配置网络

配置嵌入式 Linux 网络静态 IP 地址的脚本

#!/bin/sh

HOSTNAME=<your_host_name>
DOMAINNAME=<your_domain_name>
IP=192.168.1.99
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
NS1=114.114.114.114
NS2=8.8.8.8

# Sets the hostname 
echo 127.0.0.1 $HOSTNAME.$DOMAINNAME $HOSTNAME > /etc/hosts
/bin/hostname $HOSTNAME

# Sets up the loopback interface
/sbin/ifconfig lo 127.0.0.1 up
/sbin/route add -net 127.0.0.0 netmask 255.0.0.0 lo

# Sets up our IP and default gateway
/sbin/ifconfig eth0 $IP up
/sbin/route add default gw $GATEWAY

echo nameserver $NS1 > /etc/resolv.conf
echo nameserver $NS2 > /etc/resolv.conf

动态设备管理 udev

背景

Linux 系统 /dev 存放着设备节点的特殊文件,它是指向实际设备驱动程序的“指针”,而设备驱动程序控制和管理了应用程序对设备的访问。
在不久之前,脚本文件(如 MAKEDEV)静态创建 /dev 下大量的设备节点,而它们对应的设备实际上并不存在,给设备管理带来混乱。
为了解决这一问题,开发了 udev 设备管理子系统,它能够根据系统中实际存在的硬件动态创建 /dev 目录中的条目。

udev 工作原理

  • 当内核发现一个新的设备时,它会创建一个 uevent 事件,并通过 netlink 套接字将它发送给一个用户空间的侦听者,它正是 udev。
  • 当 udev 接收到 uevent 时,它会扫描其规则数据库:
    A 如果 udev 使用设备的属性在数据库中查找了匹配的条目,这些条目规定了它要执行的动作。
    B 如果 udev 找不到任何匹配的规则,udev 的默认动作只是创建一个设备节点,其名称由内核提供,主次设备号由 uevent 指定。

启动 mdev

拥有强大的规则引擎的 udev 一般用于 Linux 工作站,嵌入式 Linux 经常使用 busybox 版的 udev,它就是 mdev。
和 udev 一样,mdev 需要内核支持 sysfs 和热插拔。发现设备时,mdev 会在 /dev 目录中动态创建设备节点。
下面的代码清单是一个使用 mdev 的示例启动脚本。

#!/bin/sh

# mount virtual file systems
mount -t proc /proc /proc
mount -t sysfs /sys /sys
mount -t tmpfs -o size=80% /tmp /tmp # prevent greedy one from eating up all RAM
mount -t devpts /pts /dev/pts  # for SSH/Telnet

# mount /dev as a tmpfs
mount -n -t tmpfs -o mode=0755 udev /dev

# copy default static devices, which were duplicated here
cp -a -f /lib/udev/devices/* /dev

# set hotplug agent
echo "/bin/mdev" > /proc/sys/kernel/hotplug

# start busybox mdev
/bin/mdev -s

前 4 行命令创建了 4 个虚拟文件系统:/proc /sys /tmp /dev/pts
第 5 行命令将 tmpfs 挂载到 /dev 使其成为一个空目录
第 6 行命令复制一组静态设备节点到 /dev 目录
第 7 行命令将热插拔代理设置为 /bin/mdev
第 8 行命令引导 mdev 处理所有自启动后“悬而未决”的内核 uevent

配置 mdev

一个名为 /etc/mdev.conf 的配置文件用来定制 mdev 的行为,如下例所示
.* 0:0 777 将默认的访问权限改为 777 默认的 user:group 则保持不变,还是 root:root
mouse* 0:0 660 input/ 将所有鼠标设备移动到 /dev 目录的 input 子目录中。

系统关机

有几个 Linux 工具可以帮助实现关机操作,包括 shutdown halt 和 reboot 命令。关机流程如下所示:

  • 关机进程会向所有的进程发送 SIGTERM 信号,让用户进程完成自身的关机操作,比如关闭文件,保存状态等。
  • 关机进程会向所有的进程发送 SIGKILL 信号,终止用户进程。
  • 关机进程卸载所有已经挂载的文件系统,并调用与具体架构相关的关机或重启函数。
posted @ 2022-09-22 13:31  KevinAshton  阅读(231)  评论(0编辑  收藏  举报