AM335X的SD卡更新系统学习记录中最后更新完系统后,以后运行应用程序都会从EMMC中取出Linux系统运行。接着介绍Linux系统是怎么自己启动我们编写的应用程序的。

1、在AM335X的SD卡更新系统学习记录中已经详细介绍了整个系统的启动流程,这里在复述一下。AM335X上电后,根据Boot Sequence启动配置(LCD0-LCD15引脚,具体可参考TI官方的335X参考手册),从相应的存储设备启动,这里配置的是从SPI启动。内部的ROM从SPI的flash中拷贝镜像到RAM中运行。然后启动u-boot,u-boot启动后会从MMC的/sys分区的/boot目录下取出uImage镜像再到RAM中运行。Linux启动后,会接着挂接EMMC的/sys分区,启动BusyBox里的Init进程。init进程首先主要对/etc/inittab文件进行解析,然后按照它的指示创建各种子进程。inittab文件的内容主要以下几部分。其中系统运行后最先执行的是/etc/rc.d/rcS进程,并且它只执行一次,所以应用程序的启动是在这里运行的。

::sysinit:/etc/rc.d/rcS
::respawn:/sbin/getty tty1
::ctrlaltdel:/sbin/reboot
::shutdown:/etc/rc.d/rcS stop
::restart:/sbin/init

2、接着分析/etc/rc.d/rcS文件,这是一个脚本文件。这个文件的分析在AM335X的SD卡更新系统学习记录已经分析过了这里不再重复。直接看到这个脚本运行的另一个脚本/etc/rc.d/rc.local start。下面是它的内容,可以看到它的工作主要是启动daemon守护进程,应用程序由它启动,并且守护,所谓守护进程,就是不依赖于控制台会话的进程,它可以在应用程序意外退出时重新启动应用程序。如果把daemon换成应用程序,这样应用程序就能自启动了。

#!/bin/sh
mode=${:-start}
if [ $mode = "start" ]
then #set sgtl5000 volume ~
amixer cset numid= #set power led light
echo > /sys/class/leds/user_led0/brightness #start daemon
daemon # 启动守护进程 fi

3、接着分析daemon程序,它的配置文件存放在/opt/Daemon/config/daemon.xml中。主要配置的是需要启动的程序路径与名称。并且可以添加多条,其中/opt/App为目录,xxx.out为可执行文件名。并且可以设置多个路径与文件。

<ProcList Path="/opt/App" Name="xxx.out" args=""/>

4、分析到这里。可以知道一下几点。

a、存在在一个名为/opt的分区

b、其中应用程序存放在/opt/App中

c、其中daemon程序的配置文件存放在/opt/Daemon/config/daemon.xml中

d、daemon程序被放在/usr/sbin中

插上U盘后,会出现PID为13673的进程,进而出现13675、13683的进程。从这一现象可以发现./Daemon.out的另外一个作用,检测有无U盘插入,若有U盘插入的话运行/shell/udisk脚本。接下来跟着这个脚本慢慢分析。

  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
13577 root S 3.7 0.0 ./Daemon.out
root S 0.3 0.0 sh -c ./shell/udisk mount /dev/sda1
root S 0.3 0.0 {udisk} /bin/sh ./shell/udisk mount /dev/sda1
root S 0.3 0.0 {update} /bin/sh ./shell/update ./download/xxx.bin

5、开始分析以下脚本,其中$1=mount;$2=/dev/sda1。可以看到其中有一句./shell/update ./download/xxx.bin。这个脚本将在接下来分析

sh -c ./shell/udisk mount /dev/sda1
$ $ $
#!/bin/sh

case "$1" in
mount) #挂载U盘
if [ ! -b $ ] #是否存在/dev/sda1块设备装置
then
echo "$2 not exist!" #如果不存在打印出不存在,然后退出
exit
fi #cd /opt/Daemon
echo "Current Path " $(pwd) "..." #当前路径已经在Daemon中切换到/opt/Daemon中了
echo "mount $2 to /mnt/udisk..."
echo > /sys/class/leds/user_buzzer/brightness #打开蜂鸣器
mkdir /mnt/udisk #创建/mnt/udisk目录
mount -t vfat $ /mnt/udisk #以fat文件系统格式挂接/dev/sda1到/mnt/udisk echo > /sys/class/leds/user_buzzer/brightness #关闭蜂鸣器? if [ -x /mnt/udisk/xxx.bin ] #如果U盘里的xxx.bin文件可执行
then
echo "exist firmware file[xxx.bin], auto update self..."
- rm /log/x.log
cp -a /mnt/udisk/xxx.bin ./download/xxx.bin #以递归、保留符号链接的方式拷贝文件到/opt/Daemon/download中
chmod +x ./download/xxx.bin #加上可执行权限
./shell/update ./download/xxx.bin #解压出xxx.bin文件到相应的目录下
./shell/hmkill #运行/shell/hmkill 1脚本,用于杀掉现在运行的进程
./daemon.sh #运行新更新的守护进程
fi ;;
umount) #卸载U盘
if [ -d /mnt/udisk ] #如果/mnt/udisk存在
then
echo "umount /mnt/udisk..."
umount /mnt/udisk #卸载/mnt/udisk
rm -rf /mnt/udisk #删除/mnt/udisk
fi
;;
*)
echo "Usage: /shell/udisk {mount|umount}" #其它
echo
exit
;;
esac #case语句结束 exit

对以上脚本功能做一个总结:

a、挂载U盘到/mnt/udisk

b、读出U盘的MD5文件xxx.bin。并且解压出xxx.bin文件到相应的目录下。

c、杀掉现在运行的现在运行的daemon进程、app进程

d、运行新的daemon进程,这个进程会运行新的app进程

6、分析./shell/update ./download/xxx.bin。主要作用是读出U盘的MD5文件xxx.bin。并且解压出xxx.bin文件到相应的目录下,分析如下:

#!/bin/sh
# if [ ! -f $ ]          #检测文件是否存在
then
echo "$1 not exist!"
exit
fi echo > /sys/class/leds/user_buzzer/brightness #打开蜂鸣器 chmod +x $           #加可执行权限 dd if=$ of=env.sh bs= count=     #从xxx.bin读入文件放入env.sh中,每次读1字节,一共读128字节 . env.sh             #执行env.sh脚本 # 生成原始打包文件
dd if=$ of=$NAME bs= count=$SIZE skip= #从xxx.bin读入文件放入NAME中,每次读1字节,一共读SIZE字节,跳过前128个字节
# 执行脚本
MD5=`md5sum $NAME | awk '{print $1}'`  #MD5校验
if [ "$SIGN" = "$MD5" ]      #如果校验成功
then
tar -zxvf $NAME -C /        #解压
chmod +x /opt/Daemon/Daemon.out #加上可执行权限
chmod +x /opt/Daemon/shell/x   #加上可执行权限
chmod +x /opt/App/x.out #加上可执行权限
sync             #同步,立刻写入磁盘
fi rm env.sh #删除之前生成的文件
rm $NAME #删除之前生成的文件
rm $ #删除之前生成的文件 echo > /sys/class/leds/user_buzzer/brightness #关闭蜂鸣器 exit          #退出

7、制作xxx.bin的MD5文件,其中opt里存放的是App目录与Daemon目录,pack.sh是一个脚本文件,用于打包成加密的MD5格式。这个三步之后生成xxx.bin文件。放入FAT32格式的U盘,将这个U盘插入到335X的USB口即可实现更新。

a、sudo tar -czvf ./xxx.tar.gz ./opt

b、sudo chmod 755 ./xxx.tar.gz

c、sudo ./pack.sh ./xxx.tar.gz

8、分析pack.sh脚本,这个脚本的前面128字节为其他数据。与/shell/update脚本对应,/shell/update脚本会先取出前128字节。然后取出MD5签名,然后解密文件。

 # !/bin/sh
# [ $# != "" ] && echo "Usage: $0 tarfile" && exit #参数个数是否为1 FILE="reader.bin" #加密后的文件名
NAME="$1" #待加密的文件名
SIZE=`wc -c $ | awk '{print $1}'` #以字节方式计算出待加密文件大小
SIGN=`md5sum $ | awk '{print $1}'` #加密,MD5签名生成 awk处理输入的整行数据的某个字段(以空格分开)、sed处理输入的整行数据 echo "NAME=$NAME" >> $FILE # 被打包文件名称 echo "SIZE=$SIZE" >> $FILE # 被打包文件大小 echo "SIGN=$SIGN" >> $FILE # 被打包文件MD5签名 chmod +x $FILE # 加上可执行权限 dd if=$ of=$FILE bs= count=$SIZE seek= # 在被打包文件前面加上$FILE内容,共计128字节

AM335X的应用程序自启动流程以及U盘更新应用程序记录的更多相关文章

  1. [OGRE]最小ogre程序的流程

    总结一下最小ogre程序的流程: 1 创建Ogre::Root 2 用Ogre::Root加载插件,必须载入的是场景管理器和渲染器 3 调用Ogre::ResourceGroupManager::ge ...

  2. java里的分支语句--程序运行流程的分类(顺序结构,分支结构,循环结构)

    JAVA里面的程序运行流程分三大类: 1,顺序结构:顺序结构就是依次执行每一行代码 2,分支结构:分支结构就是按不同的条件进行分支 3,循环结构:一段代码依条件进行循环执行. 其中,分支结构有两大类: ...

  3. wince6.0应用程序自启动

    主要思想:将应用程序添加到image里,然后用应用程序代替桌面应用程序,从而使应用程序自启动. 主要步骤:                 1.将应用程序MyApp.exe拷贝到wince600\OS ...

  4. YARN应用程序开发流程(类似于MapReduce On Yarn)本内容版权归(小象学院所有)

    MapReduce On Yarn和MapReduce程序区别 MapReduce On Yarn(由专业人员开发)1 为MapReduce作业运行在YARN上提供一个通用的运行时环境2 需要与Yar ...

  5. linux程序自启动和新建linux服务的方法

    1 linux创建自启动程序    自启动的两种方法,都经过自己测试.1.1 自启动程序方法1:    在etc/rc.local在里面加入/home/robin/code/autoruntest & ...

  6. MFC中SDI程序创建流程的回顾

    SDI程序创建流程的回顾 从CWinApp.InitialInstance()开始, 1.首先应用程序对象创建文档模板; CSingleDocTemplate* pDocTemplate; pDocT ...

  7. 小议common lisp程序开发流程 - Ever 17 - 博客频道 - CSDN.NET

    小议common lisp程序开发流程 - Ever 17 - 博客频道 - CSDN.NET 小议common lisp程序开发流程 分类: lisp 2011-04-17 20:59 1316人阅 ...

  8. 微信小程序开发流程

    2017年1月9日,张小龙在2017微信公开课Pro上发布的小程序正式上线,一夜之间,小程序可谓家喻户晓,但通过接下来的几个月的观察,微信小程序并没有想象中的那么火爆.进入4月以来,微信小程序团队进行 ...

  9. 开发环境MAPLAB下使用仿真器ICD2程序下载流程

    程序下载流程 一.    连接示意图 二.    下载步骤 1.目标板电源断开 2.将仿真器下载端口与电路板JTAG端口有效连接 3.启动MPLAB软件 4.点击MAPLAB软件上方Programme ...

随机推荐

  1. opencv —— getTickCount、getTickFrequency 计时函数

    getTickCount 函数 返回 CPU 自某个事件(如启动电脑)以来走过的时钟周期数. getTickFrequency 函数 返回 CPU 一秒钟所走过的时钟周期数. 二者结合使用,可以用来计 ...

  2. 解决kbmMW Scheduler在任务中停止任务遇到的问题

    procedure TCustomGridViewCameraDoc.InitSchedule; begin Scheduler.Schedule( procedure(const ASchedule ...

  3. CentOS7安装gotoblas遇到的问题

    1. 错误信息: /usr/lib64/gcc/x86_64-suse-linux/4.7/../../../../x86_64-suse-linux/bin/ld: cannot find -l-l ...

  4. H5_0023:html页面禁止放大缩小页面

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scal ...

  5. Uva1363(余数性质/减少枚举量)

    题意: 输入正整数n和k(范围均为1e9),求∑(k mod i),i从1~n 解法: 首先这道题直接暴力亲测会超时. 之后我们写几组数据之后可以发现当k/i的商相同的时候他们的余数成一个等差数列,而 ...

  6. D - Counting Squares

    Your input is a series of rectangles, one per line. Each rectangle is specified as two points(X,Y) t ...

  7. 与第三方系统对接,生成Cloud出入库单据

    案例: Cloud的采购订单同步到第三方系统,第三方系统入库后同步生成Cloud采购入库单. 解决方案:调用采购订单的下推API,先生成保存状态的采购入库单(采购入库单中的仓库是必填项,可以在采购订单 ...

  8. 调用window Api 进行对特定窗口的进程ID进行操作

    /// <summary> /// 获取窗口句柄 /// </summary> /// <param name="lpClassName">&l ...

  9. elasticsearch 5.5 query 过程 源码分析

    (1)请求 transfer to  任意node 节点 标记为coordinate node server入口函数 transportSearchAction doExecute方法 coordin ...

  10. java学习笔记之反射—Class类实例化和对象的反射实例化

    反射之中所有的核心操作都是通过Class类对象展开的,可以说Class类是反射操作的根源所在,但是这个类的实例化对象,可以采用三种方式完成. java.lang.Class类的定义: public f ...