按照《Hi3531/Hi3532 Linux 开发环境 用户指南》里面说的修改rcS进行设置
程序在板子上自启动的过程中会出现问题:
1.将程序copy到/nand目录下,保存结果的文档result.txt应该在程序所在目录。
2.在/etc/init.d/rcS里的末尾添加/nand/DetectWaterDepth设置程序开机自动运行,
3.在拔掉usb转串口线之后,插拔电源重启开发板;或者在连接串口的情况下,在minicom显示界面使用reboot指令启动板子,不会生成result.txt,即使我自己写一个result.txt,也不会往里面写数据。
4.Telnet进去,kill掉程序再重启板子,程序正常运行,会(在/nand文件夹下)生成result.txt,手动启动这个程序也没有问题。
解决思路:
思路一:路径设置不对,
将路径设置为如下:依然不行
fout.open("/nand/result.txt",ios::app);
ofstream流,以ios::app打开(或者“ios::app”),如果没有文件,那么生成空文件;如果有文件,那么在文件尾追加。如果不自启的话这两种写法是都没有问题的
思路二:权限不够
经检查不是这个原因
思路三:修改rcS自启过程中出现的问题
应该是自启过程中出现的问题
老师提出方法一:把存结果的过程写进线程里
写了两个测试程序test.cpp和test_with_thread.cpp分别进行交叉编译
----开启nfs移到/nand下---rcS中设置自启动----reboot---记录结果,发现这个方法不起作用。
方法二:
1.推测是自启动过程中存在问题,了解hisiv3531启动过程发现rcS文件要比/etc/profile中的程序先执行,前面有一个细节,reboot直接启动出现问题,但telnet进入板子里kill掉程序再重启,程序会正常运行。
2.了解到linux系统启动流程可以简单总结为以下几步: https://www.jb51.net/article/145422.htm
1)开机BIOS自检,加载硬盘。 2)读取MBR,进行MBR引导。 3)grub引导菜单(Boot Loader)。 4)加载内核kernel。 5)启动init进程, init进程是Linux的根进程,所有的系统进程都是它的子进程。依据inittab文件设定运行级别 6)init进程,执行rc.sysinit文件。 7)启动内核模块,执行不同级别的脚本程序。 8)执行/etc/rc.d/rc.local 9)启动mingetty,进入系统登陆界面。 |
4)加载内核。在这个阶段,内核装入内存并在初始化每个设备驱动器时打印信息。
5).执行程序init。装入内核并初始化设备后,运行init程序。init程序处理所有程序的启动,包括重要系统程序和其它指定在启动时装入的软件。文件系统的启动过程,即linux启动过程的第二阶段,大概分为以下几个过程:
①运行init
init的进程号是1,从这一点就能看出,init进程是系统所有进程的起点,linux在完成核内引导以后,就开始运行init程序。init程序需要读取配置文件/etc/inittab,以查看下一步做什么。inittab是Linux初始化文件系统时用到的(不可执行的)配置(文本)文件,它有若干行指令所组成,告诉 init 要进入什么运行级别,以及在哪里可以找到该运行级别的配置文件。这个文件负责设置init初始化程序初始化脚本在哪里;每个运行级初始化时运行的命令; 开机、关机、重启对应的命令;各运行级登陆时所运行的命令。
②系统初始化
sysinit、boot、bootwait等action将在系统启动时无条件运行,而忽略其中的runlevel。因此init进程首先会执行etc/init.d/rcS脚本
③建立终端
rcS执行完毕后,返回init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。init接下来会打开终端,以便用户登录系统,如下:::respawn:/sbin/getty -LttyS000 115200 vt100 -n root -I "Auto login as root ...
|
至此,启动过程结束。查看/etc/inittab、/etc/init.d/rcS、/etc/profile内容。
/etc/inittab内容
::sysinit:/etc/init.d/rcS #rcS执行完毕后,返回init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。init接下来会打开终端,以便用户登录系统,如下: #在这个登录界面中会提示用户输入用户名,而用户输入的用户名将作为参数传给login程序来验证用户的身份。 #注意:如果想绕过登录验证过程,想直接进入shell界面的话,则把它注释掉,改为:::respawn:/bin/sh 启动/bin/sh程序时会启动ash的配置信息,而它就是/etc/profile,sh会把profile的所有配置全部都运行一遍,因此用户可以把自己的启动程序放在这里。 ::restart:/sbin/init #restart(重启)时执行/sbin/init ::ctrlaltdel:/sbin/reboot #按下Ctrl+Alt+Del时执/sbin/reboot ::shutdown:/bin/umount -a -r #shutdown(关机时执行)/bin/umount ::shutdown:/sbin/swapoff -a #shutdown(关机时执行)/sbin/swapoff |
/etc/init.d/rcS的内容:
#! /bin/sh #表示这是一个脚本文件,运行时用/bin/sh解析 /bin/mount -a (1)mount命令是用来挂载文件系统的 echo " \ _ _ _ _ _ ___ / /__/ \ |_/ / __ / - ____ / / / / / / _ __ _/ / / \_/ \_ ______ ___________\___\__________________ " echo [ -n ] 字符串 for initscript in /etc/init.d/S[0-9][0-9]* #GPIO17 3~6 #这四行是定义GPIO17的3~6引脚为GPIO1的功能,即用作IO管理用。地址计算为基地址0X200F0000, 再加上0X234,定义GP17.3的地址。 #这是定义GPIO17.5脚为输出引脚,即方向引脚。记住:0X400都是方向引脚,一个组只有一个寄存器 #这里直接输出17_5的引脚为高电平,引脚为高,蜂鸣器开始响了。 0X20为0B0010_0000, 也就是BIT5, 管脚号是GPIO17_0~GPIO17_7,这里的0x20260080 的数据寄存器,再加上偏移地址0X080, 计算方法为: 0X20260000 + (1 《(5 + 2))其中5为管脚号,2为右移MASK地址PADDR[9:2] ifconfig eth0 192.168.20.163 #配置ip和telnet #GPIO17_5 BUZZER #在运行了网络配置和TELNET程序后,置GPIO17_5脚为低电平,关掉蜂鸣器。 mount /dev/mtdblock3 /nand/ -t yaffs2
|
/etc/profile内容
# /etc/profile: system-wide .profilefile for the Bourne shells # # set_path_before() #设置path { [ -d $1 ] && PATH="$1:$PATH" } |
$1,$2,$3等等,指从命令行向脚本输入的第一个,第二个,第三个参数。$0指脚本本身。 由双引号括起来的字符(除$,倒引号( $1是第一个参数, -d是判断$!这个目录存不存在 如果从外面传一个参数给$1,传进来的这个参数存在且是一个目录则为真,这个为真之后执行PATH="$1:$PATH",就是把输入的路径也加进PATH变量里; |
PATH="/usr/bin:/usr/sbin:/bin:/sbin" #可执行文件路径,路径之间以冒号(:)分隔 set_path_before /usr/local/sbin set_path_before /usr/local/bin LD_LIBRARY_PATH="/usr/local/lib:/usr/lib"#库文件路径 export PATH export LD_LIBRARY_PATH |
linux中在 profile 或者 bashrc 或者其他类似的文件中设置环境变量时(比如PATH),如果没有export,那么只能在直接启动的shell中起作用,如果在当前shell下运行脚本或者直接启动一个子shell,因为实际上是局部变量。子shell看不见的,所以就gg了 简言之,export就是把本地变量变成全局变量(实际中叫环境变量), |
# ANSI COLORS CRE="^M^[[K" NORMAL="^[[0;39m" RED="^[[1;31m" GREEN="^[[1;32m" YELLOW="^[[1;33m" BLUE="^[[1;34m" MAGENTA="^[[1;35m" CYAN="^[[1;36m" WHITE="^[[1;37m" umask 022 echo "${GREEN}Welcome toHiLinux.${NORMAL}" |
之前无法建立result.txt文件,原因是环境变量放在/etc/profile 而程序执行指令放在/etc/init.d/rcS ,这里就会出现一个问题,rcS 最先被执行而profile还没被执行,PATH环境变量未全部初始化,需在执行/etc/profile 后才被添加到环境变量PATH中。
所以,尝试更改inittab的内容(::askfirst:-/nand/DetectWaterDepth中加了-会造成路径问题,不能读取config.ini或者将result.txt建在主文件夹下)
1.注释掉::respawn:/sbin/getty -LttyS000 115200 vt100 -n root -I "Auto login as root ..,
添加::respawn:/nand/DetectWaterDepth
结果:就算kill掉程序它也会自启动,只是进程号变了
添加::askfirst:/nand/DetectWaterDepth
结果:要先按回车才开始执行这个程序,每次kill掉程序,会自动等待按回车执行程序,没有终端无法运行
以上均没有生成result.txt
2.保留::respawn:/sbin/getty -LttyS000 115200 vt100 -n root -I "Auto login as root ..
添加::respawn:/nand/DetectWaterDepth
结果:开机自动运行
或::askfirst:/nand/DetectWaterDepth
结果:开机自动运行,而且不必输入回车,没有终端无法运行
以上均没有生成result.txt
3.注释掉::respawn:/sbin/getty -LttyS000 115200 vt100 -n root -I "Auto login as root ..改为
::respawn:/bash/sh+++++++++++++::respawn:/nand/DetectWaterDepth
结果:开机自动运行/输入回车自动运行,生成result.txt
4::respawn:/bash/sh,/nand/DetectWaterDepth写在etc/profile里
结果:可以实现自启动,生成result.txt,但是挂掉了不会重启,没有终端无法运行
在任何同一时刻,计算机只能执行一条指令,而且都是顺序往下执行的(除非遇到跳转指令)。Linux的进程启动都是根据启动脚本里的指令进行的,主要有两类:init 和bash. init 是所有脚本的最顶端,首先被执行,而bash一般是登陆shell 的时候才会被调用。不同的文件系统具体的启动脚本文件名称是不一样的。以yaffs为例,/etc/init.d/rcS 作为init 的脚本,理论上想开机时进入自己的应用程序,则在rcS里面写入就可以。
/etc/init.d/profile 作为bash的脚本 ,在这个脚本里的指令开机时不会被执行,但是你进入shell 状态时,就会被调用,一般来说bash 脚本多数用来存放环境变量,记住,每一次进入shell 都会调用一次bash 脚本。
存疑:能否启动之后在稍等几秒钟再新建result.txt?