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. Case Study - 用户复购行为预测

    Problem 对于商家来说提前识别回头客是一件集中资源提高新品销售量的头等大事,各大商家为了吸引顾客的二次购买都会实行各种像是促销.优惠券.折扣之类的策略.按理说越了解客户,越知道客户的喜好,越能精 ...

  2. 覆盖的面积 HDU - 1255 线段树+扫描线+离散化 求特定交叉面积

    #include<cstdio> #include<map> #include<algorithm> using namespace std; ; struct N ...

  3. 关于Git GUI克隆代码

    1.首先需要使用Git GUI生成一个SSH秘钥并将其拷贝到远程(码云或者GitHub)账号下的SSH公钥中(以码云为例) 将上一步生成的SSH密钥拷贝到下面的码云的公钥中 2.拷贝下码云上代码的SS ...

  4. Spark学习之路 (二十七)图简介[转]

    test test test test test test test test test 图 基本概念 图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种数据结构. 这里的图并非 ...

  5. PAT (Basic Level) Practice (中文)1043 输出PATest (20 分)

    给定一个长度不超过 1 的.仅由英文字母构成的字符串.请将字符重新调整顺序,按 PATestPATest.... 这样的顺序输出,并忽略其它字符.当然,六种字符的个数不一定是一样多的,若某种字符已经输 ...

  6. (三)运用Python模块和包

    1 引言 为了能够在Python项目中高效地运用Python模块和包,我们需要进一步地来了解它们是如何在Python项目中进行定义.使用和工作的. 2 Python模块和包 Python模块和包的基本 ...

  7. Hadoop报错:org.apache.hadoop.security.AccessControlException: Permission denied: user=xxxx

    问题出现原因: 因为远程提交hadoop的任务的情况下如果,没有hadoop 的系统环境变量,就会读取当前主机的用户名,所以Hadoop集群的节点中没有该用户名的权限,所以出现的异常. 解决方法: S ...

  8. 518-零钱兑换 II(完全背包-求方案总数)

    518-零钱兑换 II(完全背包-求方案总数) 给定不同面额的硬币和一个总金额.写出函数来计算可以凑成总金额的硬币组合数.假设每一种面额的硬币有无限个. 示例 1: 输入: amount = 5, c ...

  9. XSS漏洞原理

    注入型漏洞的本质都是服务端分不清用户输入的内容是数据还是指令代码,从而造成用户输入恶意代码传到服务端执行. 00x01js执行 Js是浏览器执行的前端语言,用户在存在xss漏洞的站点url后者能输入数 ...

  10. openWRT和LuCI

    openwrt是一套集成在板子上的系统,通过ip进入到其页面上 Luci是lua和UCI统一配置接口的合体,实现路由的网页配置界面(相当于一个前端框架)