一般来说,嵌入式设备的程序是上电自动运行的。设备系统启动后会自动运行某些系统级脚本(/ect/rc3.d/下的脚本),最终会运行我们自定义的脚本,在该脚本中会运行应用程序。——这就是系统自动启动的一般做法。
在测试中,发现如果升级在升级程序过程中断电(测试人员故意的,以模拟某些实际可能也许不会发生的事),则设备无法再启动。我们的设备使用硬盘存储系统文件,所谓“升级”,就是把程序文件写到磁盘分区某个目录上。深入了解后,发生写的文件大小全为0,当然是不正确的,程序无法执行,设备启动就不正常了。——根本原因是,恰好有一个自定义的脚本文件size为0,这个文件挂了,后面的过程就无法顺利执行了。后来想到一招。把核心的脚本单独升级,并且保证这个升级一定成功。其后的程序升级则无须升级该核心脚本。 在这个过程中,引发了另一个题目的小问题。虽然前文所述的值得深究,但不是本文重点。 启动脚本会去读一些文件的配置,使用exec的形式。下面的例子是读取bar文件,并判断其值是否为0,为0执行a.out(q.out为死循环,目的是为了a.out不退出)。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ########读文件内容 if [ -f bar ]; then exec 3< bar read NUM <&3 echo $NUM # 判断是这样 if [ "X$NUM" = "X0" ] then echo "NUM is 0" ./a.out else echo "NUM not 0" fi fi
查询一下a.out进程所占用的文件描述符。结果如下:
1 2 3 4 5 6 7 8 9 10 11 root@localhost:~# ps -ef | grep a.out root 12409 12405 0 08:55 pts/0 00:00:00 ../a.out root 12412 12386 0 08:55 pts/1 00:00:00 grep --color=auto a.out root@localhost:~# ll /proc/12409/fd total 0 dr-x------ 2 root root 0 Jul 27 08:55 ./ dr-xr-xr-x 7 root root 0 Jul 27 08:55 ../ lrwx------ 1 root root 64 Jul 27 08:55 0 -> /dev/pts/0 lrwx------ 1 root root 64 Jul 27 08:55 1 -> /dev/pts/0 lrwx------ 1 root root 64 Jul 27 08:55 2 -> /dev/pts/0 lr-x------ 1 root root 64 Jul 27 08:55 3 -> /mnt/latelee/test/simple_test/shell/bar
我们看到,脚本使用exec 3< bar将bar的内容读取文件描述符3里,由于a.out是一直循环,所以会一直占用着该描述符。 我们看另一个例子,不使用exec,而是直接用cat。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ######## 另一种方式 if [ -f bar ]; then # 只截至第一行的内容 NUM1=`cat bar | head -1` echo $NUM1 # 判断是这样 if [ "X$NUM1" = "X0" ] then echo "NUM1 is 0" ./a.out else echo "NUM1 not 0" fi fi
再次看a.out进行的文件描述符,结果如下:
1 2 3 4 5 6 7 8 9 10 11 root@localhost:~# ps -ef | grep a.out root 12418 12414 0 08:56 pts/0 00:00:00 ../a.out root 12420 12386 0 08:56 pts/1 00:00:00 grep --color=auto a.out root@localhost:~# ll /proc/12418/fd total 0 dr-x------ 2 root root 0 Jul 27 08:56 ./ dr-xr-xr-x 7 root root 0 Jul 27 08:56 ../ lrwx------ 1 root root 64 Jul 27 08:56 0 -> /dev/pts/0 lrwx------ 1 root root 64 Jul 27 08:56 1 -> /dev/pts/0 lrwx------ 1 root root 64 Jul 27 08:56 2 -> /dev/pts/0 root@localhost:~#
我们看到,脚本已经不占用文件描述符了。 对于这个问题,似乎有点吹毛求疵,但很多时候遇到的问题,往往是小细节引发的,这不得不让我提高敏感度。 文中使用/proc/进程ID/fd目录查看指定进程的文件描述符,这个方法还是比较有用的,下文即将提到。
2015.7.30 李迟