ByToradex胡珊逢
1.简介
文件系统对于嵌入式系统,正如记忆对于脑部,嵌入式系统丧失了文件系统,这常常是严重的问题,轻则造成应用未能启动,数据遗失,严重的情况可能是整个系统启动失败。Windows笔记本的死机、手机变砖,这其中很大比列是因为重要系统文件遗失、损坏所致。怎样保护嵌入式文件系统的安全,这是系统开发人员构筑一款稳定、可靠产品时应当考虑的事情。
损毁文件系统,不仅外部诱因如高压、高温、强磁场干扰储存器外,写文件系统那时的忽然掉电常常会导致文件系统结构本身的损毁,比如分区信息。在Linux嵌入式系统常见的挂载VFS失败就是因为rootfs破损所致,而这之前的U-Boot和Linuxkernel常常任可以正常工作。文件针对这种情况,将介绍怎样在iMX6平台上,怎么使用只读文件系统,并将用户应用和数据保存在独立的分区,以及借助ToradexEasyInstaller完成分区和系统安装操作。
2.生成只读文件系统
Yocto/OpenEmbedded建立框架的一个特征是,系统软件会依据所建立的目标镜像的要求手动调整编译软件的功能。诸如在IMAGE_FEATURES中添加read-only-rootfs,这么BSP中包含的软件将不会往Flash上写入文件linux文件系统只读,包括系统日志。
在local.conf配置
------------------------------------
EXTRA_IMAGE_FEATURES="debug-tweakspackage-managementread-only-rootfs"
DISTRO_EXTRA_RDEPENDS_remove="angstrom-libc-fixup-hack"
------------------------------------
3.设置分区挂载
更改用户分区挂载目录
------------------------------------
layers/meta-toradex-demos/recipes-core/base-files/base-files/fstab
/dev/root/autoro,noatime11
proc/procprocdefaults00
devpts/dev/ptsdevptsmode=0620,gid=500
usbdevfs/proc/bus/usbusbdevfsnoauto00
tmpfs/runtmpfsmode=0755,nodev,nosuid,strictatime00
tmpfs/var/volatiletmpfsdefaults00
#uncommentthisifyourdevicehasaSD/MMC/Transflashslot
#/dev/mmcblk0p1/media/cardautodefaults,sync,noauto00
/dev/mmcblk0p3/mntext4defaults,sync,noauto00
------------------------------------
将系统根目录设置为只读状态,并将独立的用户分区挂载到/mnt目录,该目录任具有读写权限。用户应用可以在该分区下保存用户配置文件、应用日志,甚至升级用户应用本身。
4.设置应用自启动脚本
因为文件系统须要配置为只读属性arm linux,我们须要在Yocto/OpenEmbedded建立时直接包含应用开机启动脚本。目前Toradex的LinuxBSP早已采用systemd启动管理,用户须要添加对应的systemdservice文件。为了便捷演示,我们直接在layers/meta-toradex-bsp-common/recipes-core/目录下创建用户自己的recipe文件linux文件系统只读,如user-demo,其实你也可以在Yocto/OpenEmbedded根目录中添加自己的layerlinux cp,将所需的recipe都包含进来,具体方式请参考这儿。
------------------------------------
tdx_cn_ben@LinuxDevSH1:~/Toradex/OE/v2.7/layers/meta-toradex-bsp-common/recipes-core/user-demo$tree-L2
├──files
│└──user-demo.service
└──user-demo.bb
------------------------------------
user-demo.bb
------------------------------------
SUMMARY="Adduserdemo"
DESCRIPTION="createfolderwithinhomeandinstallauto-runservicescript"
LICENSE="CLOSED"
PR="r3"
SRC_URI="
file://user-demo.service
do_install(){
install-m0644${WORKDIR}/user-demo.service${D}${systemd_unitdir}/system
NATIVE_SYSTEMD_SUPPORT="1"
SYSTEMD_PACKAGES="${PN}"
SYSTEMD_SERVICE_${PN}="user-demo.service"
inheritallarchsystemd
------------------------------------
user-demo.service
------------------------------------
[Unit]
Description=launchuser'sdemoondedicatedpartition
ConditionFileIsExecutable=/mnt/helloworld
StartLimitIntervalSec=200
StartLimitBurst=5
After=multi-user.target
[Service]
Type=simple
ExecStart=/mnt/helloworld
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
------------------------------------
启动脚本中使用ConditionFileIsExecutable来判定用户分区是否成功挂载并存在可执行文件,等待分区文件打算完成后才启动,同时设置Restart,当启动失败后会再度尝试。
最后执行命令,生成用于ToradexEasyInstaller的安装文件
------------------------------------
bitbakeconsole-tdx-image
------------------------------------
将下边文件复制到SD或则U盘中
------------------------------------
├──Colibri-iMX6_Console-Image.bootfs.tar.xz
├──Colibri-iMX6_Console-Image.rootfs.tar.xz
├──image.json
├──prepare.sh
├──slides_vga
├──SPL
├──toradexlinux.png
├──u-boot.imx
├──userapp.tar.xz
└──wrapup.sh
------------------------------------
5.更改image.json配置文件
ToradexEasyInstaller中的image.json文件可用于配置iMX6模块上Flash的分区情况,并将文件写入对应的分区中。我们须要在Flash创建分区,储存用户文件userapp.tar.xz,并去除rootfs分区want_maximised属性。
------------------------------------
"want_maximised":false,
"content":{
"mkfs_options":"-Enodiscard",
"filesystem_type":"ext4",
"uncompressed_size":140.03515625,
"filename":"Colibri-iMX6_Console-Image.rootfs.tar.xz",
"label":"RFS"
},
"partition_size_nominal":512
},
"want_maximised":true,
"content":{
"mkfs_options":"-Enodiscard",
"filesystem_type":"ext4",
"uncompressed_size":7.01,
"filename":"userapp.tar.xz",
"label":"UserData"
},
"partition_size_nominal":512
------------------------------------
userapp.tar.xz压缩包中包含了用户文件,如helloworld和taq.mp4,直接将其压缩成xz格式即可。
6.用户应用
因为用户应用储存在独立的分区上,因而并不须要将其集成到Yocto/OpenEmbedded,利用ToradexEasyInstaller可以直接将程序、数据等写入分区。以下边应用为例,应用将复印“Helloworld!”,并在用户分区上写如数据文件。该应用由前面的user-demo.service脚本在开机时启动。
------------------------------------
intmain(intargc,char*argv[]){
intfile_hd;
unsignedchardata[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
file_hd=open("/mnt/log-file",O_CREAT|O_WRONLY|O_TRUNC);
if(file_hd==-1)
printf("filecreatefailed");
return-1;
write(file_hd,(unsignedchar*)data,16);
close(file_hd);
printf("Helloworld!n");
return0;
------------------------------------
7.测试文件系统
查看挂载情况
------------------------------------
root@colibri-imx6:/etc/udev/rules.d#mount-l
/dev/mmcblk0p2on/typeext4(ro,noatime,data=ordered)[RFS]
……
/dev/mmcblk0p3on/media/mmcblk0p3typeext4(rw,relatime,data=ordered)[UserData]
------------------------------------
在只读文件系统上难以创建目录
------------------------------------
root@colibri-imx6:~#pwd
/home/root
root@colibri-imx6:~#mkdirtestfolder
mkdir:can'tcreatedirectory'testfolder':Read-onlyfilesystem
------------------------------------
UserData分区下的用户文件
------------------------------------
root@colibri-imx6:/media/mmcblk0p3#ls
helloworldlost+foundtaq.mp4
------------------------------------
应用启动情况
------------------------------------
root@colibri-imx6:~#journalctl-uuser-demo.service