4.4.2. 集成用户软件进系统镜像
在开发过程中,常常需要将一些配置文件或开发完成的程序直接包含到系统镜像中,以便在设备运行时能够在板端直接使用这些文件或程序。本章将详细介绍两种常用的方法,将用户的软件和文件集成到系统镜像中:
将文件添加到根文件系统的
system分区这种方式适用于需要直接与系统文件一同部署的文件,例如系统库、系统配置文件等。通过将文件放入
system分区,可以确保它们在设备启动时即可被加载和使用。新增一个独立的分区存放自定义文件
通过创建新的分区并将自定义文件、程序存放其中,可以实现更高的灵活性和模块化。新分区会生成独立的镜像文件,方便管理和更新,同时也能避免对根文件系统的影响。
这两种方法各有特点,可根据需求选择合适的集成方式来优化开发和部署流程。以下将分别介绍两种方法的使用。
4.4.2.1. 将文件添加到根文件系统的 system 分区
将用户自定义文件集成到根文件系统非常简单。只需将准备好的文件复制到路径 system/buildroot/prebuilt/boot-utils-runtime 下。在编译 system 镜像时,这个目录中的所有内容都会被自动打包到 system 分区中,无需额外操作。合并这部分文件的编译代码在 BSP 源码的 build/mk_system.sh 脚本中,实现代码如下:
function build_unpack()
{
... ( 省略 ) ...
# 合并自动启动配置项
if [ -d "${SYSTEM_ORIG_DIR}/boot-utils-runtime" ]; then
rm -rf "${SYSTEM_BUILD_DIR}"/etc/dropbear
cp -arf --remove-destination ${SYSTEM_ORIG_DIR}/boot-utils-runtime/* "${SYSTEM_BUILD_DIR}"
fi
}
注意事项:
system分区的容量具体大小可能因软件版本有所不同。如果添加的文件导致分区总大小超过预设容量,镜像生成将失败。为避免此问题,可以通过修改分区表来调整system分区的大小。详细方法请参考分区配置。
在操作前,请确认 system 分区容量限制,并确保添加的文件不会超出可用空间。
4.4.2.2. 新增独立分区存放自定义文件
为更灵活地管理程序或配置文件,可以通过新增一个独立分区专门存放这些内容。这种方式特别适合需要对程序进行独立编译、管理和升级的场景。本节以配置 app 分区为例,详细说明操作步骤(app 分区默认已支持)。
注意事项
关于分区表最后一个分区
如果新增的分区位于分区表的最后一个分区之后(例如在
userdata分区之后),需要注意以下行为:系统启动时,
Uboot阶段会根据硬件存储设备(如 eMMC 或 NAND Flash)的实际容量,自动将最后一个分区扩展至存储设备的末尾,以最大化利用存储空间。首次启动时,
Kernel检测到最后一个分区未被格式化或没有有效的文件系统时,会自动执行格式化操作。
userdata分区默认设置系统镜像制作时,
userdata分区通常是最后一个分区,不包含数据,且分区大小设置较小(默认 50MB),以减小镜像体积。启动后,
Uboot会自动扩展userdata分区到剩余存储空间,首次进入系统时会格式化该分区。如果在
userdata之后新增分区,请调整userdata的大小以满足实际需求。
关于空分区
如果新增分区在镜像制作时为空(无有效数据,如
userdata或private),需要在系统首次启动时进行格式化。格式化逻辑可以参考
/etc/init.d/S65mountall脚本,将新分区名添加到force_format_part_list变量中,例如:force_format_part_list="app userdata log private"
实现步骤
1. 修改分区表
在分区表中定义新分区。以 device/horizon/x5/board_cfg/soc/x5-soc-debug-gpt.json 为例,添加如下配置:
"app": {
"fs_type": "ext4",
"part_type": "GOLDEN",
"size": "700m"
},
fs_type:分区文件系统类型,设置为ext4。size:分区大小,单位为 MB(示例为700m)。
有关分区表配置的更多信息,请参考分区配置。
2. 准备分区内容
创建一个用于存放分区文件的目录(如 app),并在其中添加需要的文件。例如,添加一个名为 startup.sh 的启动脚本:
# 在 BSP 源码根目录下执行以下命令
mkdir app
cd app
echo "#!/bin/sh" > startup.sh
echo 'echo "This is the test code"' >> startup.sh
chmod 777 startup.sh
若新增分区为空,此步骤可跳过。当前系统中 /app 和 /userdata 目录下的 startup.sh 程序会被 /etc/init.d/S99auto_startup 服务在系统启动时调用执行。
3. 验证生成分区镜像
参考以下编译程序,根据分区目录内容生成镜像,例如:
./build/mk_app.sh
生成的镜像文件位于 out/product/app.img。若新增分区为空,可跳过此步骤。
4. 集成编译脚本
在 xbuild.sh 中添加分区编译逻辑:
在
avail_func中添加分区选项:avail_func=("all" "lunch" "miniboot" "uboot" "factory" "boot" "hbre" "system" "app" "pack" "otapackage")
定义
build_app函数:function build_app { is_exist=$(get_part_exist app) if [ "$is_exist" = "0" ]; then return fi build_component "app" "${HR_LOCAL_DIR}/mk_app.sh" "$@" }在整体编译逻辑中加入
app分区:if [ -d "${HR_TOP_DIR}/app" ]; then build_app "$opt" fi
以上代码添加完成后,可通过 ./bd.sh app 或 ./mk_app.sh 编译生成 app.img。
5. 自动挂载新分区
在系统中添加新分区后,为确保分区能在启动时自动挂载,需要在 system/buildroot/prebuilt/boot-utils-runtime/etc/hb-fstab 文件中添加对应的挂载配置。例如,新增 app 分区的挂载配置如下:
/dev/block/platform/by-name/app /app ext4 defaults 0 1
以下是各字段的含义及相关注意事项:
设备路径 (
/dev/block/platform/by-name/app)指定分区设备的路径。
根据设备和分区配置,此路径可能有所不同,请确保与实际设备路径一致。
挂载点 (
/app)指定分区挂载的目标目录。
系统启动时,分区内容将挂载到此目录下。
需要确保该目录已在镜像制作过程中创建,否则系统将无法挂载分区,可能导致启动失败。例如在
mk_system.sh的build_unpack函数中添加目录创建逻辑:mkdir -p ${SYSTEM_BUILD_DIR}/{app,log,userdata,usr/hobot,data,private}
文件系统类型 (
ext4)指定分区的文件系统类型。
根据分区的实际文件系统格式选择合适的值(如
ext4、vfat等)。此处必须与分区表中配置的
fs_type一致。
挂载选项 (
defaults)使用默认挂载选项。
defaults是一个预定义的选项集合,它包括了以下特性:rw(读写模式):允许对分区进行读写操作。suid(允许设置用户 ID):允许执行文件的 SUID(Set User ID)和 SGID(Set Group ID)权限。这允许某些程序在执行时以文件所有者的权限运行。dev(允许设备文件):允许分区中存在设备文件(如/dev目录中的文件)。exec(允许执行文件):允许在分区中执行文件。auto(自动挂载):允许分区在系统启动时自动挂载。nouser(不允许普通用户挂载):只有 root 用户或具有特定权限的用户才能挂载该分区。async(异步 I/O):允许异步 I/O 操作,提高性能。
在
app分区的挂载配置中,defaults选项的具体含义如下:分区设备
/dev/block/platform/by-name/app将以读写模式挂载到挂载点/app。分区中的文件可以设置 SUID/SGID 权限,以支持特定程序的权限需求。
分区中的文件可以被系统执行,确保应用程序的正常运行。
分区将在系统启动时自动挂载,无需手动干预。
只有 root 用户或具有特定权限的用户可以挂载该分区,以增强系统的安全性。
I/O 操作将以异步方式执行,从而提高分区的性能表现。
defaults选项可以确保分区在挂载时具备基本的读写和执行权限。如果需要自定义挂载参数,可根据需求替换为实际参数。例如:
ro:只读挂载。rw:读写挂载(默认)。noexec:禁止执行分区中的二进制文件。nosuid:禁止设置 SUID 和 SGID 标志位。
备份标志 (
0)指定该分区是否需要
dump备份。设置为
0表示不备份,是通常设置为0。
文件系统检查顺序 (
1)指定系统启动时检查文件系统的顺序。
0表示不检查该分区。非零值表示检查顺序,数字越小,优先级越高。
6. 打包分区进系统镜像
完成所有配置后,可以通过编译脚本生成分区镜像,并把新增的分区镜像 pack 到系统镜像中。
使用以下命令执行完整编译和打包流程:
./bd.sh
如果新增的分区是空分区(即在镜像生成时未包含实际数据,如 userdata 分区),可以选择跳过该分区的镜像打包操作。在 xbuild.sh 脚本的 truncate_fill_image 函数中,可以按如下方式调整逻辑:
# FIXME: If there is actual data in the partition behind the mirror, pack will be skipped.
# 先固定跳过 log 和 userdata 分区,要优化成根据配置来找到最后一个有数据的分区
case "${part_name}" in
log*|userdata*|app*)
rm -f "${HR_TARGET_PRODUCT_DIR}/${part_name}".img
;;
esac
完成以上步骤后,新增的分区(如 app 分区)将被编译并合并到系统镜像中。
如需验证,可以检查镜像文件 out/product/app.img 是否存在,并通过刷机或启动系统验证新增分区的功能是否正常。
验证
完成刷机后:
系统启动时如果用户通过串口连接设备,那么可以在串口的打印日志上看到
This is the test code的日志输出,说明/app/startup.sh已经运行。使用
fdisk -l查看分区表,确认app分区存在,大小为700MB(分区大小需要和实际的分区表配置对齐)。使用
mount确认分区已挂载至/app。使用
ls /app查看分区内容,确认startup.sh存在并可执行。示例输出:
# ls /app/ startup.sh lost+found