简述
嵌入式Linux系统一般是将应用程序与文件系统、内核、资源文件等放在不同的分区,产品量产后内核、文件系统这些一般不会升级,应用程序可能升级会比较多一些。
有的嵌入式系统的应用程序分区用的也是可读写的,那比较方便,把文件打包然后解压到对应的分区目录下替换即可。有的是应用分区做成只读,这样需要将应用程序打包做成flash镜像,下载到设备上更新到flash上。
不论是那种方式,对于应用程序来说都需要打包起来,可以是压缩包,也可以是镜像文件。这些文件在导入到系统进行升级的时候,我们都需要对这个文件做一些必要的验证,比如:版本号、版本标志、校验等;版本号一般用于显示提醒;版本标志是针对该型号设备的不同配置所做的标记(如几个串口、是4G版还是以太网版等);文件校验是对文件的合法性进行检查,以免文件错误导致升级后程序无法启动。
升级文件的制作与版本信息添加
那么这些信息加在哪里?怎么加呢?常见以下几种方式:
- 直接将升级文件以型号+版本标识+版本号进行命名,然后给文件加个校验;之前我们使用过这种方式,这种方式比较简单,但是也有个弊端,就是文件名称容易被人修改,或者传输过程中容易被修改,文件名称一旦被修改,那么信息也就丢了。
- 专门再添加一个文本文件,用于存储这些信息;两个文件不便于保存。
- 将信息写入升级文件里;这种方式相对来说比较好一些,信息直接写入该文件里,验证的时候再从文件里去取。需要注意的是升级文件一定要小于分区大小。
下面介绍的主要是第三种方式,将信息写入到升级文件里。那么怎么写入升级文件里呢?下面介绍一种简单实用的方法。
下面的制作过程是在虚拟机Ubuntu系统下面进行的,以制作squashfs格式镜像为例。将版本信息、标志以及校验码都追加在文件的最后,可以直接用echo命令将这些信息追加在文件的最后,当然校验码是c语言写的一个小工具添加的(参见《给文件添加CRC校验》)。
追加版本信息与标识信息的命令如下:
echo "V1.0.1" >> app.img echo "F-P4-4G" >> app.img #注意这里一定要用">>",而不是">",用">>"是追加,用">"是清空文件重新写入。
测试一下
下面是我测试的一个制作升级文件的目录,目录文件结构如下:
$ls app bin package.sh
app 是应用程序的目录
bin 制作完成的升级文件存放目录
package.sh 打包制作脚本,用于生成镜像文件
package.sh脚本内容如下:
#!/bin/sh if [ $# -ne 2 ] then echo "Usage: package.sh <version no> <flag info>" exit fi VNum=$1 #版本信息 Flag=$2 #版本标识信息 installDir=./bin #升级文件存储目录 tmpName="app" rootDir="app" #要打包的应用程序目录 #*************************************************** Ver=`date '+%Y%m%d'` #取时间作为版本信息的一部分 echo "start make app img..." echo $Ver> $rootDir/version echo $VNum >> $rootDir/version imgName="test_app-$Ver-V$VNum.img" echo "app version: $Ver, version num: V$VNum" echo "make squashfs img ..." mksquashfs $rootDir $imgName -b 64K -comp xz echo "package app img ok! " echo "V$Ver $VNum" >> $imgName #追加版本信息 echo "F$Flag" >> $imgName #追加标识信息 addCrc16 $imgName #校验文件,并把校验码加入升级文件,addCrc16是c语言写的一个给文件添加校验的程序 rm $imgName #删除临时文件 mv $imgName.crc16 $installDir/$imgName echo "mkfs ok: $installDir/$imgName"
执行该脚本制作文件:
$./package.sh 1.0.1 -P2-4G start make rootfs... app version: 20210924, version num: V1.0.1 make squashfs img ... Parallel mksquashfs: Using 4 processors Creating 4.0 filesystem on test_app-20210924-V1.0.1.img, block size 65536. [=============================================================================/] 33/33 100% Exportable Squashfs 4.0 filesystem, xz compressed, data block size 65536 compressed data, compressed metadata, compressed fragments, compressed xattrs duplicates are removed Filesystem size 621.31 Kbytes (0.61 Mbytes) 32.52% of uncompressed filesystem size (1910.41 Kbytes) Inode table size 302 bytes (0.29 Kbytes) 64.81% of uncompressed inode table size (466 bytes) Directory table size 155 bytes (0.15 Kbytes) 100.00% of uncompressed directory table size (155 bytes) Number of duplicate files found 0 Number of inodes 10 Number of files 4 Number of fragments 1 Number of symbolic links 2 Number of device nodes 0 Number of fifo nodes 0 Number of socket nodes 0 Number of directories 4 Number of ids (unique uids + gids) 1 Number of uids 1 fens (1000) Number of gids 1 fens (1000) make suqashfs img ok! file size = 639000 file crc16 = 0x001d add crc16 ok! mkfs ok: ./bin/test_app-20210924-V1.0.1.img
查看文件
文件生成后,让我们来看下升级文件里我们添加的信息。
可以用Uedit来查看一下文件,这里只截取最后的一部分看下我们添加的信息:
如上图,三部分信息已标出,在做文件信息的检测时,就可以读取文件中的这些信息进行判断处理了。
读取版本信息的c语言示例代码
char readBuf[128] = {0}; FILE *fp = fopen("app.img", "r"); int ret = fseek(fp,-10L,SEEK_END);//偏移到版本号开始的位置。 fread(buf,16,1,fp); //读取版本号 ret = fseek(fp,-10L,SEEK_END); //偏移到版本标识信息的位置 fread(buf,16,1,fp); //读取版本标识信息