按照《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 ...
- 在115200 bps的虚拟终端ttyS000上启动一个登陆会话 (注意getty的用法)
- getty进程接收到用户名后,启动login进程.
- login进程要求用户输入口令.
- 用户输入口令.
- login进程对username和password进行检查.
- login启动shell进程.
- shell进程根据/etc/password中的shell类型,启动相应的shell.并启动/etc/profile文件和$HOME/.bash_profile文件.最后出现shell提示符,等待用户输入命令.
至此,启动过程结束。查看/etc/inittab、/etc/init.d/rcS、/etc/profile内容。
/etc/inittab内容
::sysinit:/etc/init.d/rcS
#rcS执行完毕后,返回init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。init接下来会打开终端,以便用户登录系统,如下:
::respawn:/sbin/getty -L ttyS000 115200 vt100 -n root -I "Auto login as root ...
#以respawn方式运行getty程序,它会显示一个文本登录界面,这个界面就是我们经常看到的登录界面,
#在这个登录界面中会提示用户输入用户名,而用户输入的用户名将作为参数传给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命令是用来挂载文件系统的
(2)mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找
一个文件/etc/fstab文件,这个文件不仅仅用来控制mount -a的行为,一般的mount命令也受它控制,
它按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)
echo "
_ _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ ___
/ /__/ |_/
/ __ / - ____
/ / / / / /
_ __ _/ / / \_/ \_ ______
___________\___\__________________
"
echo是一种最常用的与广泛使用的内置于Linux的bash和C shell的命令,通常用在脚本语言和批处理文件中来在标准输出或者文件中显示一行
文本或者字符串,在终端下打印变量value的时候也是常常用到的,在这里起到一个提示的作用。
echo [ -n ] 字符串
其中选项n表示输出文字后不换行;字符串能加引号,也能不加引号。用echo命令输出加引号的字符串时,将字符串原样输出;
用echo命令输出不加引号的字符串时,将字符串中的各个单词作为字符串输出,各字符串之间用一个空格分割。
for initscript in /etc/init.d/S[0-9][0-9]*
do
if [ -x $initscript ] ;
then
echo "[RCS]:$initscript"
$initscript
fi
done
#判断是不是第一次安装系统,如果是,则检查并且执行安装程序留下的脚本
#GPIO17 3~6
himm 0x200F0234 0
himm 0x200F0238 0
himm 0x200F023C 0
himm 0x200F0240 0
#这四行是定义GPIO17的3~6引脚为GPIO1的功能,即用作IO管理用。地址计算为基地址0X200F0000, 再加上0X234,定义GP17.3的地址。
#GPIO17 DIR
himm 0x20260400 0x20
#这是定义GPIO17.5脚为输出引脚,即方向引脚。记住:0X400都是方向引脚,一个组只有一个寄存器
#GPIO17_5 BUZZER
himm 0x20260080 0x20
#这里直接输出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
ifconfig eth1 192.168.1.163
telnetd&
#配置ip和telnet
#GPIO17_5 BUZZER
himm 0x20260080 0x0
#在运行了网络配置和TELNET程序后,置GPIO17_5脚为低电平,关掉蜂鸣器。
mount /dev/mtdblock3 /nand/ -t yaffs2
cd /nand/ko
./load3531
/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?