嵌入式 Linux 系统在线升级策略-固件升级-升级固件-系统升级

2023-11-07

如果你认为本系列文章对你有所帮助,请大家有钱的捧个钱场,点击此处赞助,赞助额1元起步,多少随意

锋影

email:174176320@qq.com


嵌入式 Linux 系统在线升级策略

对于运行 Linux 系统的嵌入式产品,很多时候我们发现了当前版本内核、驱动、或者应用程序的 bug 并对之修复之后,或者研发出了功能更丰富、性能更突出的应用软件时,想要对当前运行的设备进行相应程序替换和升级。很多人的做法是通过对每一台设备烧写新版软件的方式进行软件版本更新,如果产品数量少且分布地点比较集中,这种方案具有一定的实效性。但是当设备数量庞大且地点分散时,这种本地烧写的升级方式将会变得非常难以操作,且升级结果可视化具有一定难度,需要通过串口等终端才能确认。

针对采用 Linux 系统且具有互联网接入能力的嵌入式设备,不论这种接入方式是有线网络、wifi、2G 或者 4G,本文将为其提供一种通过服务端后台对在线的所有或者部分设备进行远程批量升级的高效、可靠、直观的升级策略。升级内容可以是内核、驱动、文件系统、应用程序或者某些配置文件。接下来,将首先展示该方案的架构图,紧接着一步步讲述各个功能或者逻辑模块的细节。

方案概述

此升级方案由后台服务端程序、web 页面、终端升级程序三部分组成。如图 1 展示了升级方案 的架构图。

图 1. 升级方案架构图

自动草稿

自动草稿

服务端程序

服务端程序用来监测终端设备状态,管理升级包,升级流程控制并且提供 web 端响应以及数据库访问。本策略中的服务端为 apache-tomcat,程序采用 java servlet,数据库为 MySQL,web 页面为 JSP 编写。您可以使用任何一种后台语言(如 php、python 等)实现本文所描述的服务端功能。

服务端功能有:

  • 终端消息处理
  • 升级包管理
  • 升级指令处理

终端消息处理

服务端程序通过 getParameter("version")获得终端软件版本号,通过 queryLatestVersion()查询数据库中最新软件版本号,然后将二者进行对比。如果相同,则证明该终端设备软件版本已经是最新,返回 latest 指令;如果不同且服务端没有收到 web 端用户的升级指令,则通过 queryAddress()从数据库中查询最新升级包的地址,将之返回给终端,以便终端设备从该地址下载升级包,另外,如果此时用户在 web 界面执行了升级命令,则返回 update 指令给终端,终端设备执行升级操作。详细请查看清单 1。

清单 1. 终端消息处理代码片段
public void doGet(HttpServletRequest request, HttpServletResponse response)\
throws ServletException, IOException {
    String msg = null;
    String version_latest = null;
    String address_latest = null;
    String version = request.getParameter("version");

    PrintWriter out = response.getWriter();
    version_latest = queryLatestVersion();
    if(version.equals(version_latest)){ 
        msg = "|latest|null|null|";
    }else if(UpdateServlet.update_status){
        msg = "|update|"+version_latest+"|null|";
        UpdateServlet.update_status = false;
    }else{
        address_latest = queryAddress();
        msg = "|download|172.x.x.x"+address_latest+"|"+MD5+"|";
    }
    out.print(msg);
    out.flush();
    out.close();
}

升级包管理

服务端程序处理 web 端上传的升级包,首先确认存放升级包的路径是否存在,没有则创建。升级包接收完成之后,从升级包文件名中截取版本号,然后将文件名、版本号、升级包在服务端的存放路径信息插入到数据库中。类似的,服务端程序也响应 web 端用户对升级包的更改、删除等操作。详细的升级包管理请查看清单 2。

清单 2. 升级包管理代码片段
protected void doPost(HttpServletRequest request,\
    HttpServletResponse response) throws ServletException, IOException {
    String uploadPath = "/xx/xx";
    File uploadDir = new File(uploadPath);
    if (!uploadDir.exists()) {
        uploadDir.mkdir();
    }
    try {
    List<FileItem> formItems = upload.parseRequest(request);
    if (formItems != null && formItems.size() > 0) {
         for (FileItem item : formItems) {
             if (!item.isFormField()) {
                 String fileName = new File(item.getName()).getName();
                 Patternp=Pattern.compile("update_package-(.*?).tar.gz");
                 Matcherm=p.matcher(fileName);
                 while(m.find()){
                     version = m.group(1);
                 }
                String filePath = uploadPath + File.separator + fileName;
                sql = "INSERT INTO package(name,version,address)\
                VALUES('"+fileName+"','"+version+"','"+filePath+"');";
                dbOperate(sql);
                File storeFile = new File(filePath);
                item.write(storeFile);
                request.setAttribute("message",\
                "Package Has beed uploaded successfully!");
            }
        }
   }
   } catch (Exception ex) {
        request.setAttribute("message","error info: " + ex.getMessage());
    }
}

升级指令处理

如果用户从 web 端选择了升级设备并且点击了升级按钮,服务端程序则会记录该指令,当下一次收到终端设备的 POST 消息时,则会对指定的终端下发 update 升级指令,终端收到 update 命令后执行升级程序。升级完成之后终端会再次周期性上报其版本号,通过 web 端设备列表即可查看所有设备升级结果,做到升级流程、结果的可视化。

终端升级程序

终端升级程序由升级管理程序和升级执行程序两部分组成。本文所描述的升级策略先决条件是构建合理的磁盘、Flash 分区,以便支持本策略中各种程序的正常运行。

终端磁盘分区示例

图 2. 终端设备磁盘分区图

自动草稿

自动草稿

图 2 是一个针对本策略的基本 Flash 分区示例。Flash 的总容量为 128M,第一个分区为启动分区,用来存放启动 Linux 系统的引导程序,容量 2M;第二个分区为 Linux 内核分区,用来存放 Linux 内核镜像文件,容量 8M;第三个分区为根文件系统分区,用来存放根文件系统镜像文件且作为运行时用户操作空间,容量 100M;第四个为备份分区,用来存放想要备份的内容,以便升级完成后被拷贝到新的文件系统中,容量 16M;最后一个为固化信息分区,用来存放设备软件版本号、设备类型、设备 id 等信息,容量 2M。该分区信息仅作为参考,分区数量、大小需要根据具体项目做相应修改。当然如果项目没有特殊性,且硬件资源与该示例匹配,此分区方案亦可直接被沿用。

升级管理程序

升级管理程序功能如下:

  • 管理软件版本信息
  • POST 设备信息给服务端
  • 从服务端下载升级包
  • 校验,管理升级包
  • 启动升级执行程序

升级管理程序随着系统开机启动且作为守护进程运行。第一次运行时从宏定义中读取软件版本号并固化到 info 分区中,每隔一段时间从 info 分区中读取设备类型、设备 id、软件版本号。并将这些信息通过 HTTP POST 给服务端。服务端收到设备信息之后解析出其中的软件版本号,并和数据库中的最新升级包版本号进行对比。如果升级包版本号高于设备版本号,则返回 download 指令以及升级包地址、升级包 MD5 码给终端设备。

表 1. 终端设备信息消息格式
设备 id 设备类型 软件版本
000001 家庭网关 1.0.1
000002 摄像头 1.0.2
表 2. 服务端返回消息格式
指令 参数 1 参数 2
download <ip>/dir/update_package.<version>.tar.gz <MD5 code>
update <update package version> null
latest null null

表 1、表 2 分别展示了终端设备发送、服务端返回的消息格式以及内容。

升级管理程序收到服务端返回消息对其解析,根据不同指令做如下响应:

  • 指令为 download,则根据参数 1 提供的地址下载对应的升级包到终端设备本地的 tmp 目录中。下载完成之后取得升级包的 MD5 码和参数 2 中的进行对比,完成升级包校验。
  • 指令为 update,则把参数 1 中的版本号和本地 tmp 目录中的升级包版本号进行对比,如果相同才会启动升级执行程序进行升级。
  • 指令为 latest,则证明当前终端设备的软件版本和服务端中的最新升级包版本相同,已经是最新版本,不予理会。

升级执行程序

升级执行程序功能如下:

  • 解压升级包
  • 备份文件
  • 格式化内核、文件系统分区
  • 加载升级包中的文件到内核、文件系统分区
  • 重启操作系统
  • 拷贝备份文件到文件系统中

当升级执行程序被升级管理程序启动之后,首先解压升级包,并对之校验、检测。如果检测通过则开始备份用户文件,需要说明的是 backup 分区挂载在文件系统根目录 backup 文件夹上,因此备份方式是将需要备份的文件拷贝到 backup 文件夹中且记录其原始路径。下一步进行内核、文件系统分区格式化操作,此后将升级包中新版的内核镜像、文件系统镜像写到内核、根文件系统分区中,完成新老替换。然后自动重启操作系统,启动成功之后,将备份文件拷贝到对应的文件系统路径中。此时的终端设备升级完毕,运行新版系统和软件。如果升级内容仅仅为应用程序或者配置文件,则只需进行相应文件的替换即可。

设备和服务端的交互

终端设备通过 HTTP 协议与服务端进行交互。终端程序每隔 10 秒向服务端 HTTP POST 发送一次设备信息,服务端根据版本号对比结果以及 web 端升级指令状态返回三种不同指令给终端设备。终端通过解析指令做出相应响应。其中下载功能调用 libcurl 库,具有断点续传能力。10 秒的请求频率可根据具体项目应用场景做出调整,如果终端数量比较少且服务端能够承受连接压力,想要响应更加快速、及时,可考虑将 HTTP 改为 socket 长连接的通信方式。

web 端

Web 端提供用户进行升级操作的人机接口,显示、接收、跟踪整个升级过程。采用 JSP 编写。其功能如下:

  • 显示设备状态。显示设备在线、离线状态、设备类型、设备 id、软件版本号。
  • 升级包管理。显示所有升级包,对已有的升级包进行修改、删除等操作。上传新的升级包。
  • 升级操作管理。用户可通过设备列表多选、全选设备,点击升级按钮生成升级指令。

总结

本文提供了一种远程在线方式对嵌入式 Linux 设备进行批量升级的策略,升级内容包括内核、驱动、文件系统、应用程序、配置文件等。能够快速、稳定完成升级操作。描述了服务端程序、终端设备升级程序、web 端功能、设备和服务端交互方式,完整地展示了升级流程的细节,供开发者参考。

需要注意的是,该策略的实施过程中,需要确保升级设备具有足够电量以保证升级程序的顺利执行。该策略仅仅提供功能性的描述,为了确保可靠性和适应更加复杂的环境,开发者需要增加双分区启动备份机制。此外,由于升级包存放在 tmp 目录中,因此可支持的升级包大小受限于内存物理空间,开发者可将升级包存放在指定磁盘分区对该功能进行优化。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式 Linux 系统在线升级策略-固件升级-升级固件-系统升级 的相关文章

  • 如何在C程序中直接改变显存映射来绘制像素(无需库函数)

    是否可以通过使用 C 程序更改 RAM 中屏幕 视频即监视器 内存映射中的值来显示黑点 我不想使用任何库函数 因为我的主要目标是学习如何开发简单的操作系统 我尝试访问起始屏幕内存映射 即 0xA0000 在 C 中 我尝试运行该程序 但由于
  • 设置 Vim 背景颜色

    当我尝试更改背景颜色时 vimrc或者直接在 Vim 中使用以下命令 set background dark 这根本不影响我的背景 也没有light选项 不过 当我运行 gvim 时 看起来还不错 有没有办法在不更改 Konsole 设置的
  • “./somescript.sh”和“. ./somescript.sh”有什么区别

    今天我按照一些说明在 Linux 中安装软件 有一个需要首先运行的脚本 它设置一些环境变量 指令告诉我执行 setup sh 但是我执行时犯了一个错误 setup sh 所以环境没有设置 最后我注意到了这一点并继续进行 我想知道这两种调用脚
  • PHP 日志文件颜色

    我正在编写一个 PHP 日志文件类 但我想为写入文件的行添加颜色 我遇到的问题是颜色也会改变终端的颜色 我想要实现的是仅更改写入日志文件的行的颜色 class logClass extends Singleton private funct
  • php56 - CentOS - Remi 仓库

    我刚刚在测试盒上安装了 php 5 6 正常的 cli php 解释器似乎不存在 gt php v bash php command not found gt php56 v PHP 5 6 13 cli built Sep 3 2015
  • 即使使用 rvm pkg install zlib 后也无法加载此类文件 -- zlib

    我使用 rvm 安装了 zlib 包和 ruby 1 9 3 但是每当我尝试安装时 它说宝石cannot load such file zlib 我用来安装的命令是 rvm install 1 9 3 rvm pkg install zli
  • Linux 阻塞与非阻塞串行读取

    I have 这段代码 https stackoverflow com questions 6947413 how to open read and write from serial port in c用于在Linux中从串行读取 但我不
  • python 可以检测它运行在哪个操作系统下吗?

    python 可以检测操作系统 然后为文件系统构建 if else 语句吗 我需要将 Fn 字符串中的 C CobaltRCX 替换为 FileSys 字符串 import os path csv from time import strf
  • 有没有办法只安装mysql客户端(Linux)? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有没有不需要安装整个mysql db安装包的Linux mysql命令行工具 我想做的是从服务器 1 应用程序服务器 执行将在服务器 2
  • 如何从命令行执行 PHP 代码?

    我想执行单个 PHP 语句 例如if function exists my func echo function exists 直接使用命令行 无需使用单独的 PHP 文件 这怎么可能 如果您要在命令行中执行 PHP 我建议您安装phpsh
  • 如何防止 CMake 在构建时(而不是安装时)为共享库创建符号链接?

    我正在使用 CMake 在 Linux 上使用 Bullet3 构建一个项目 在构建整个解决方案时 它会构建附加了 SOVERSION 的 Bullet 输出库 并创建一个不带版本的符号链接 对于我的特定场景 我不喜欢这种行为 并且我不想编
  • _dl_runtime_resolve -- 共享对象何时加载到内存中?

    我们有一个对性能要求很高的消息处理系统 最近我们注意到第一条消息比后续消息花费的时间要长很多倍 当它通过我们的系统时 会发生大量转换和消息增强 其中大部分是通过外部库完成的 我刚刚描述了这个问题 使用 callgrind 将仅一条消息的 运
  • 如何在 Linux 中显示进程状态(阻塞、非阻塞)

    有没有办法查询 Linux 进程表中进程的状态 以便能够演示执行查询时进程是正在运行还是被阻止 我的目标是从进程或程序的 外部 执行此操作 因为我希望从操作系统进程的角度来理解这一点 但欢迎任何想法 这是Python代码阻塞的过程 impo
  • 选择多个模式的 awk 代码

    这是我的输入文件 比如modified txt r4544 n479826 2012 08 28 07 12 33 0400 Tue 28 Aug 2012 1 line Changed paths M branches 8 6 0 con
  • Linux shell 标题大小写

    我正在编写一个 shell 脚本并有一个如下所示的变量 something that is hyphenated 我需要在脚本中的各个点使用它 如下所示 something that is hyphenated somethingthati
  • C/C++ with GCC:静态地将资源文件添加到可执行文件/库

    有人知道如何使用 GCC 将任何资源文件静态编译为可执行文件或共享库文件吗 例如 我想添加永远不会改变的图像文件 如果它们改变了 我无论如何都必须替换该文件 并且不希望它们位于文件系统中 如果这是可能的 我认为这是因为 Visual C f
  • 对于客户端服务器程序,并行接收多个客户端连接请求的最佳方法是什么?

    该程序是在 Linux 上用 C 语言开发的客户端服务器套接字应用程序 每个客户端都连接到一个远程服务器并将其自身记录为在线 在任何给定时间点很可能有多个客户端在线 所有客户端都尝试连接到服务器以将自己记录为在线 忙碌 空闲等 那么服务器如
  • Python 线程与 Linux 中的多处理

    基于此question https stackoverflow com questions 807506 threads vs processes in linux我假设创建新流程应该几乎和创造新线程在Linux中 然而 很少的测试显示出截
  • C 标准库函数与系统调用。哪个是“open()”?

    I know fopen 在C标准库中 所以我绝对可以调用fopen C 程序中的函数 我感到困惑的是为什么我可以打电话给open 功能也一样 open 应该是系统调用 所以它不是标准库中的C函数 因为我能够成功地调用open 函数 我调用
  • 我如何知道 std::map 插入成功还是失败?

    我在多线程应用程序中有一个映射 将名为 uuid 的类映射到指针 我想知道插入操作是否成功或失败 e g mymap insert hint MyMap value type entry uuid itemptr 如果失败的话会抛出异常或者

随机推荐

  • hive 表中常用的 增加/修改/替换列操作

    1 语法 更新列 ALTER TABLE table name CHANGE COLUMN col old name col new name column type COMMENT col comment FIRST AFTER colu
  • C++ 仿函数(二)

    在上一篇里我们讲了仿函数是什么 以及一元谓词 二元谓词的概念 C 仿函数 一 小梁今天敲代码了吗的博客 CSDN博客 这篇是讲 内建函数对象 主要包括 算术仿函数 关系仿函数 逻辑仿函数 目录 一 算术仿函数 示例 二 关系仿函数 示例 举
  • windows 开机启动脚本(亲测可用)

    1 打开计划任务 2 创建任务 3 添加一个启动触发器 4 添加一个脚本操作 5 点击确认 输入登录管理员密码即可 重启试试吧
  • 部署 Exsi 7.0.3

    文章目录 1 下载介质 2 u盘引导安装启动盘 3 硬件连接 4 安装 EXSI 7 0 3 1 下载介质 下载 VMware VMvisor Installer 7 0U3l 21424296 x86 64 iso 安装 EXSI 7 0
  • vue H5页面跳转微信小程序以及生成二维码跳转小程序

    研究了两种H5跳转小程序的方法 同时携带参数 1 手机浏览器打开H5页面 点击按钮拉起微信小程序 2 H5页面上生成小程序二维码 手机微信扫码跳转目标小程序 为了开发方便 以上两种均借助了微信小程序云函数来实现 事前准备 在vue工程的in
  • Oracle数据库的导入&导出

    1 权限配置及导入导出 1 1 配置导入导出目录及设置相应权限 SQL gt select from dba directories dir where dir DIRECTORY NAME in DUMPDIR DATA PUMP DIR
  • 百万youtube高清视频数据集采集

    HD VILA 100M是什么 HD VILA 100M是一个大规模 高分辨率 多样化的视频语言数据集 有助于多模态表示学习 数据统计 该数据集共包含330万个视频 视频质量较高 均衡分布在15个类别中 下载 Download 您可以通过此
  • 详解34家银行对公账号编码规则及其编码分析

    1 工商银行 账号位数19位 地区代码4位 13为安徽 网点号4位 账户性质应用号2位 09基本户 19一般户 29专户 39临时户 账号顺序号7位 校验码2位 编码分析攻略 中国工商银行对公账户共19位 其中1 4位为地区代码 详见代码表
  • 树莓派教程 - 1.0 树莓派GPIO库wiringPi 点亮LED

    Git例程源码仓库 https github com ZhiliangMa raspberry git 电脑需要提前安装的工具 SSH 串口 终端神器 MobaXterm 官网下载链接 https mobaxterm mobatek net
  • java.sql.sQLException: No suitable driver found for jdbc:mysql

    用Maven构建父工程后 再搭建DAO模块 执行测试类测试StudentDao java查询数据库功能报错 定位到相应的类中 发现是数据库连接问题 之前我也遇到类似的问题 解决方案为 jdbc url jdbc mysql localhos
  • YOLO系列目标检测算法-Scaled-YOLOv4

    YOLO系列目标检测算法目录 文章链接 YOLO系列目标检测算法总结对比 文章链接 YOLOv1 文章链接 YOLOv2 文章链接 YOLOv3 文章链接 YOLOv4 文章链接 Scaled YOLOv4 文章链接 YOLOv5 文章链接
  • 主业工资5000,靠“爬虫技术”月入20000:会赚钱的人,从不靠拼命

    因为我们主行业的一个内卷以及薪资问题 现在已经有很多人都在从事一个副业 副业往往比主业更自由 轻松 甚至有的副业工资比他的一个主业工资还高 现在 只要你会python的爬虫技术 网上接单副业的项目更是多的供过于求 现在业界对Python爬虫
  • Python和OpenCV 提取图像特定目标区域-图像分割【原创】

    在OpenCV中 一般转换图像格式为HSV格式 默认格式为BGR 再进行指定颜色的提取 直接使用RGB提取颜色不推荐 HSV格式的介绍 HSV 为色相 饱和度 明度 1 将一副图像从rgb颜色空间转换到hsv颜色空间 hsv cv2 cvt
  • <Visual Studio 2019安装及环境配置教程>

    目录 1 Visual Studio 2019下载安装 1 1 进入官网 1 2 选择所需Visual Studio 2019安装包 1 3 Visual Studio 2019 版本说明 1 4 点击下载 安装 1 5 登录账户 1 6
  • 2022年华中杯数学建模挑战赛B题量化投资问题求解全过程文档及程序

    2022年华中杯数学建模 B题 量化投资问题 原题再现 量化投资是指通过数量化方式及计算机程序化发出买卖指令 以获取稳定收益为目的的交易方式 投资者通过数据分析探索市场运行规律 并预测市场走势 从而进行决策交易 随着大数据技术的发展 量化投
  • windows11安装wsl

    wsl2 简单点说 就是可以在Windows上用Linux 并且支持docker 管理员身份打开powerShell win x 输入下面命令 wsl install dism exe online enable feature featu
  • 算法(C++)金币阵列问题

    题目描述 有m n m 100 n 100 个金币在桌面上排成一个m 行n 列的金币阵列 每一枚金币或正面朝上或背面朝上 用数字表示金币状态 0 表示金币正面朝上 1 表示背面朝上 金币阵列游戏的规则是 1 每次可将任一行金币翻过来放在原来
  • 从mpeg ts文件中提取I帧(3):pes包的解析

    本系列的第一篇文章讲解了如何把ts包拼装为pes包 本章主要讲解如何解析pes包 一 pes包的格式如下图所示 二 相关字段解析 packet start code prefix 标识包起始端的包起始码 固定值为 0000 0000 000
  • 沟通——职场生存的润滑剂

    我们每天都有和别人沟通互动 但经常不经意地话不投机或语出伤人都不自知 在工作中 沟通也是必不可少的 经常听到企业的领导强调沟通 上下级沟通 同事间沟通 的确 沟通可以大大提升工作效率 沟通是一种技能 是一个人对本身知识 表达能力 行为能力的
  • 嵌入式 Linux 系统在线升级策略-固件升级-升级固件-系统升级

    如果你认为本系列文章对你有所帮助 请大家有钱的捧个钱场 点击此处赞助 赞助额1元起步 多少随意 锋影 email 174176320 qq com 嵌入式 Linux 系统在线升级策略 对于运行 Linux 系统的嵌入式产品 很多时候我们发