嵌入式系统现场更新全攻略
1. 现场更新基础操作
在进行现场更新时,首先要进行一些基础操作。在工具环境目录下创建符号链接:
$ cd tools/env
$ ln -s ./fw_printenv fw_setenv
当
fw_printenv
被复制到目标机器时,也需要复制或重新创建这个符号链接。该程序依据板卡配置中存储的闪存布局来确定要更改闪存中的哪些内存区域。如果更改了板卡的闪存布局,就需要重新编译此程序,否则它会将数据写入错误的闪存区域。
接下来在目标系统上开展工作,从更新服务器获取根文件系统并存储到当前根文件系统中:
$ wget http://yourdomain.com/path/to/new/rootfilesystem/newrfs.
U - Boot 引导加载器允许环境变量引用其他环境变量,这些引用在板卡启动时会被展开。由于可能会更改用于启动设备的根文件系统,因此需要在 U - Boot 环境中创建如下的内核命令行:
UBOOT> setenv bootargs 'console=ttyS1 rootfstype=jffs2 root=${rootdev}'
环境变量
${rootdev}
在引导加载器环境中被设置为生产根文件系统。在新的根文件系统写入闪存设备后,可运行
fw_setenv
命令来更改根文件系统。示例脚本如下:
FLASH_DEVICE=/dev/mtd4
mtderase $FLASH_DEVICE
if mtdcopy /tmp/newrfs $FLASH_DEVICE ; then
fw_setenv rootdev $FLASH_DEVICE
fi
下次系统重启时,就会使用新的根文件系统。
2. 自主更新方式
除了上述方法,还可以选择自主处理更新。这种方式的主要优点是可靠性高,因为可以完全掌控整个过程。不过,使用系统上的高级工具进行文件打包、压缩以及从远程主机获取数据,能避免大多数底层编码问题,但这会使解决方案占用更多资源。
所有的包管理工具都是基于底层归档工具的封装。例如,
dpkg
和
ipgk
基于
tar
和
gzip
,而
RPM
则使用
cpio
和
gzip
。如果只需要最基本的包管理功能,使用
tar
和
zip
就能创建出一个简单有效的解决方案,虽然没有那些高级功能,但足以将更新推送到目标计算机。鉴于 BusyBox 有处理
tar
和
cpio
文件格式的工具,这两种格式是比较合理的选择。是否进行压缩可根据应用程序的大小和板卡的内存情况来决定。
下面是一个自主更新的示例:
首先,在开发主机上创建一个目录
<build dir>
来存放要发送到目标设备的文件:
<build dir>/
lib/
libapp.so.0
libapp.so -> libapp.so.0
bin/
appfile
然后在脚本文件中创建该目录的
tar
文件:
BUILDDIR=<build-dir>
OUTPUTFILE=<output-file>
tar -C $BUILDDIR tf $OUTPUTFILE *
将输出文件发送到目标机器,并从根目录解压以安装其内容。使用
ftpget
获取
tar
文件的脚本如下:
if ftpget -u username -p secret \
hostname /tmp/newfile.tar ; then
tar -C / -xf /tmp/newfile.tar
done
将新代码部署到系统后,需要重启应用程序以使更改生效。
3. 使用包管理工具
在桌面系统中,包管理工具很常见,几乎每个 Linux 发行版都基于一组基础包编译并制作成 ISO 镜像来启动系统。包管理系统能够跟踪系统中先前安装的内容,还能记录单个包的相关信息,如包中的文件、分组信息以及为使包内软件正常运行所需安装的其他包列表。包依赖信息会与在线数据库关联,包管理软件可以通过该数据库下载包及其所有依赖项。
使用包管理系统要求设备的根文件系统以读写模式挂载,使用闪存的设备通常使用 JFFS2 或 YAFFS2 。如果设备使用只读文件系统,包管理器就无法在该介质上执行更新操作。不过,并非整个根文件系统都需要以读写模式挂载,只需包管理软件写入文件和保存数据库的部分为读写模式即可。
常见的包管理系统有用于桌面系统的 RPM 和 dpkg ,还有专为嵌入式系统设计的 ipkg 。使用包管理系统的一个好处是可以在远程站点创建包存储库,软件能在一次事务中下载新包及其相关包。例如,如果软件需要包一、二、三和包三所需的 A 和 B ,包管理软件可以根据包依赖信息下载这些包并在安装应用程序之前完成安装。
下面是几种常见包管理工具的详细介绍:
3.1 RPM
RPM 由 Red Hat 开发,用于维护公司发行版的构建和安装。在嵌入式系统中,RPM 可以像在桌面系统中一样安装包。从远程系统下载包可通过与 RPM 包配合使用的 YUM 程序完成,也可以不使用 YUM 单独使用 RPM。
创建二进制 RPM 需要编写一个 spec 文件,该文件告知 RPM 从何处查找要添加到归档文件的文件、文件类型以及安装时的权限设置。很多人认为只能通过编译源 RPM 来创建 RPM ,但实际上可以通过创建一个简单的规范文件来查找要复制到目标的文件列表,而无需考虑这些文件的构建方式。
以下是一个示例 spec 文件,用于从其他地方构建的包创建二进制 RPM:
Summary: Embedded Application
Name: embedded-app
Version: 1.1
Release: 001
Group: Applications/Misc
URL: http://your.url
Packager: Resource 1,
BuildRoot: %_buildsystem
License: GNU
%description
The application for the target system
%files
%defattr(-,root,root)
/usr/bin/appfile
/usr/lib/libapp.so.0
/usr/lib/libapp.so
为了正确构建,需要创建
~/.rpmmacros
文件:
%_buildsystem %(echo $HOME)/<build dir>
%_targetcpu arm
%_topdir %(echo $HOME)/<output dir>
RPM 构建过程会从
<build dir>
读取文件,该目录与目标设备的根文件系统结构一致,然后在
<output dir>
目录中创建 RPM 文件。这些目录可以位于机器的任意位置,示例中为了简单使用了主目录。创建这些文件后,使用以下命令读取 spec 文件进行构建:
$ rpmbuild -v -bb --target arm app.specfile
Building target platforms: arm
Building for target arm
Processing files: embedded-app-1.1-001
Requires(rpmlib): rpmlib(CompressedFileNames) \
<= 3.0.4-1 rpmlib(PartialHardlinkSets) \
<= 4.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): \
/usr/lib/rpm/check-files /home/gene/book-code/build
Wrote: /home/gene/book-code/output/RPMS/arm/embedded-app-1.1-001.arm.rpm
构建完成后,有两种方式安装 RPM 文件:将其复制到目标并使用 RPM 安装,或者创建存储库并使用 YUM 管理文件及其依赖项的复制。
以下是使用 RPM 安装文件的示例:
# 定义要复制的文件列表和目标应用程序名称
FILELIST="file.list md5"
APP_NAME="your_app"
# 从远程机器获取文件并放入 /tmp 目录
for f in $FILELIST; do
if ! ftpget -u username -p secret \
hostname /tmp/$f /remote/path/$f ; then
echo "failed to download file $f"
exit 1
done
# 检查文件下载是否正确
if ! md4sum -c /tmp/md5 > /dev/null ; then
echo "list of files not downloaded properly"
fi;
# 安装 RPM 文件
while read f ; do
if ! rpm -i $f ; then
echo error installing $f
exit 4
fi
done < /tmp/file.list
# 删除临时文件
for f in $FILELIST; do
rm /tmp.$f
done
# 重启应用程序
killall $APP_NAME
使用 YUM 时,YUM 系统与 RPM 文件配合,可下载 RPM 及其所有依赖项,并将它们安装到目标系统。不过,YUM 并非适用于所有系统,因为它依赖 Python ,某些系统可能没有足够的存储空间来安装所需文件。
使用 YUM 需要创建一个可被目标板卡访问的存储库,创建步骤如下:
# 下载 createrepo 工具
$ wget http://createrepo.baseurl.org/download/createrepo-0.4.11.tar.gz
$ cd createrepo-0.4.11/
$ make
$ sudo make install
# 创建 YUM 存储库
$ createrepo $REPO_DIR
Saving Primary metadata
Saving file lists metadata
Saving other metadata
将存储库内容放置在 HTTP 服务器可访问的位置,记为
REPO_URL
。然后在目标板卡上构建和配置 YUM :
# 下载并构建 YUM
$ wget http://yum.baseurl.org/download/3.2/yum-3.2.24.tar.gz
$ tar xzf yum-3.2.24.tar.gz
$ cd yum-3.2.24.tar.gz
$ make
$ sudo make install DESTDIR=/path/to/board/rfs
# 创建 YUM 配置文件
[embedded]
name = EmbeddedApp
baseurl = file:///tmp/output/repodata
# 创建缓存
$ sudo yum makecache
embedded 100% |================| 951 B 00:00
Metadata Cache Created
# 检查缓存内容
$ yum repolist
repo id repo name status
embedded EmbeddedApp enabled: 1
repolist: 1
整个更新流程可以用如下 mermaid 流程图表示:
graph LR
A[开始] --> B[基础操作]
B --> C{选择更新方式}
C -->|自主更新| D[创建目录并打包]
C -->|使用包管理工具| E{选择包管理系统}
D --> F[发送并解压文件]
F --> G[重启应用程序]
E -->|RPM| H[编写 spec 文件]
E -->|dpkg| I[编写控制文件]
E -->|APT| J[创建 APT 存储库]
H --> K[构建 RPM 文件]
K --> L{安装方式}
L -->|直接安装| M[复制并安装 RPM]
L -->|YUM 管理| N[创建 YUM 存储库]
N --> O[配置 YUM]
O --> P[创建缓存并检查]
I --> Q[构建 dpkg 文件]
Q --> R[安装 dpkg 文件]
J --> S[添加包到存储库]
S --> T[使用 APT 工具更新]
M --> G
P --> G
R --> G
T --> G
G --> Z[结束]
通过以上步骤,你可以根据实际需求选择合适的更新方式和包管理工具,确保嵌入式系统的顺利更新。
嵌入式系统现场更新全攻略
4. dpkg 包管理系统
Debian 包管理系统是 Debian 发行版的底层包管理系统,像 Ubuntu 等流行的基于 Debian 的发行版也在使用。该系统和 RPM 系统类似,需要创建一个包含包元数据的文件,然后将这些元数据和软件组合成一个包,供其他程序在系统上安装软件。Debian 有源码包和二进制包的概念,理想状态下应该从源码构建二进制包,但并非所有项目都适用,所以也可以直接从二进制文件构建包。这个包管理系统还能创建一个包存储库,供远程客户端请求最新版本的包及其依赖项。下面介绍如何创建一个简单的包和存储库。
4.1 创建 dpkg 包
创建 dpkg 包需要使用控制文件,这和使用 spec 文件创建 RPM 文件类似。参考之前 RPM 的示例项目,下面是同一个二进制项目的 Debian 包控制文件:
Package: embedded-app
Version: 1.1
Section: application
Priority: required
Architecture: arm
Essential: yes
Installed-Size: 1024
Maintainer: Resource 1 <resource1@company.url>
Description: The application for the target system,
now with positive electrons,
just like marketing asked!
这个文件包含了描述包的元数据,安装包的设备可以通过比较包的架构、版本等信息来判断是否是合适的文件。这个示例展示了创建一个包所需的最少信息,能让我们专注于创建包和在存储库中使用包的高级过程。
在示例包中,文件被构建到一个名为
build/
的目录,其结构类似于设备上的根文件系统:
build/
lib/
libapp.so.0
libapp.so -> libapp.so.0
bin/
appfile
为了让 dpkg 构建这个目录(使用默认文件位置,这是最简单的方式),需要将控制文件命名为
DEBIAN/control
,目录结构如下:
build/
lib/
libapp.so.0
libapp.so -> libapp.so.0
bin/
appfile
DEBIAN/
control
控制文件放置正确后,使用 dpkg 构建命令来构建包:
$ dpkg -b build embedded-app.deb
dpkg-deb: building package `embedded-app' in `embedded-app.deb'
包构建完成后,如果想查看其内容,可以使用
less
命令快速预览:
$ less embedded-app.deb
4.2 远程更新 Debian 包
当
embedded-app.deb
文件在目标系统上后,BusyBox 包含了一组用于安装 Debian 包的小程序。获取并安装这些包的过程和 RPM 示例类似,只是将 RPM 替换为 dpkg,修改后的脚本部分如下:
while read f ; do
if ! dpkg -i $f ; then
echo error installing $f
exit 4
fi
done < /tmp/file.list
脚本的其余部分完全相同。实际上,可以将执行安装的命令定义为一个宏,方便测试两种系统,选择更合适的一种,但注重资源的嵌入式工程师通常不会这样浪费资源。
5. 使用 APT 进行包管理
如果不想手动创建和维护一个用于确定下载内容的脚本,或者现场系统的配置差异较大,简单的下载并安装包列表的脚本无法满足系统更新需求,那么可以使用 Debian 的 APT(Advanced Packaging Tool)工具。其中,
apt-get
是类似于 YUM 的工具,可以创建一个包含依赖信息的包池,用户可以一次操作获取一个包及其所有依赖项。
创建 APT 存储库的步骤如下:
1.
获取必要工具
:
$ sudo apt-get install reprepro
-
创建存储库目录
:可以在
/tmp目录下创建(也可以选择其他有写入权限的目录):
mkdir -p /tmp/apt/conf
mkdir -p /tmp/apt/incoming
-
创建存储库配置文件
:存储库需要一个配置文件,让客户端访问时知道能找到哪些类型的包。以下是一个适合嵌入式设备文件的示例配置文件,需保存为
/tmp/apt/conf/distributions:
Origin: Embedded Company
Label: Embedded Device Software
Suite: stable
Codename: edasich
Version: 1.0
Architectures: arm
Components: main
Description: This is an embedded code repository for an embedded device
-
将包添加到存储库
:使用以下命令将
embedded-app文件添加到存储库:
$ reprepro -b /tmp/apt includedeb edasich \
<path to package>/embedded-app.deb
Exporting indices...
- 验证包是否在存储库中 :
$ reprepro -b /tmp/apt list edasich
edasich|main|arm: embedded-app 1.1
存储库准备好后,需要在目标板卡上准备好运行 APT 工具。由于 APT 工具是用 C++ 编写的,不需要像 YUM 那样依赖 Python 等额外工具。
6. 不同包管理工具对比
| 包管理工具 | 适用场景 | 依赖工具 | 构建方式 | 安装方式 | 资源占用 |
|---|---|---|---|---|---|
| RPM | 桌面系统和嵌入式系统 | cpio、gzip、YUM(可选) | 编写 spec 文件 | 直接使用 RPM 或通过 YUM 管理 | 相对较大,YUM 依赖 Python |
| dpkg | Debian 及基于 Debian 的发行版 | tar、gzip | 编写控制文件 | 使用 dpkg 命令 | 适中 |
| APT | Debian 系统,需要自动处理依赖 | reprepro | 创建存储库和配置文件 | 使用 apt-get 等工具 | 适中,不依赖 Python |
在选择包管理工具时,可以根据系统的特点、资源情况和更新需求来综合考虑。例如,如果系统资源有限且不需要复杂的依赖管理,dpkg 可能是一个不错的选择;如果需要自动处理大量依赖关系,且系统有足够资源支持 Python,那么 RPM + YUM 或 APT 会更合适。
通过以上对嵌入式系统现场更新的多种方式和包管理工具的介绍,你可以根据实际情况灵活选择合适的方法,确保系统的稳定更新和高效运行。无论是自主更新还是使用包管理工具,都需要根据系统的具体需求和资源状况进行权衡和选择。同时,在更新过程中要注意备份重要数据,避免因更新失败导致系统故障。
嵌入式系统现场更新指南
超级会员免费看
118

被折叠的 条评论
为什么被折叠?



