您的浏览器不支持CSS3,建议使用Firfox、Chrome等浏览器,以取得最佳显示效果

EasyBoot的shell的脚本设计

硬件嵌入式相关 273℃ 0 3年前 (2014-11-19)

正在筹划EasyBoot上实现shell,思考了一阵之后确定了实现的方案,事先声明:我并没有学习过程序语言设计,更没有关于任何程序语言设计的经验,这只是根据我个人的编程经验和技巧做出的设计。欢迎反馈,欢迎建议和意见,如果对EasyBoot项目感兴趣,可以访问我的github主页https://github.com/EmbolismSoil。
设计:
EasyBoot为了兼容多种硬件,命令段中会存在大量的命令,并且往后随着事件的发展和硬件性能的提升也会导致命令量会增长,基于这样的事实,shell的设计如下:

cmd对象:拥有一个方法,一个参数链表,一个真子命令链表(返回值为真时调用),一个伪子命令链表(返回值为假时调用)。一个args成员记录参数个数,一个ret成员记录命令返回码。外加帮助信息,还有一个_pri的空指针给位用户自行使用,shell不对此进行要求,另外该对象维护一个使用计数位,用于排列命令。

shell对象:有一个通用的输出和输入方法,通用输入输出方法通过一个FIFO缓冲池对象来隔离。缓冲池保留一个消息计数位,和消息缓存。shell还有张内置变量表。
shell拥有有命令队列,需要执行的命令会被加入队列当中,队列当中的命令可以通过管道进行通信,以此支持命令之间协同工作,并且支持bash当中的||和&&逻辑(根据命令执行的返回值确定是否执行下一条语句),以及 判断语句(这个实际上是一个命令),if else语句。目前决定实现支持命令手动输入,待文件系统支持完善,会考虑利用脚本文件进行工作,但是事先会考虑工作量的问题再决定是否实现脚本。
shell拥有一个命令池(实际上是连接时确定的命令段),还拥有命令链表(如果用户需要大量的指令,会考虑使用堆结构),命令先从命令链表中查找,若查找不到,则到命令池中查找,命令池使用过的命令会从命令池中加入命令链表。每次命令调用都会传入shell对象的指针(this)还会导致命令计数更新并且queue标志位被置位,通知shell可在适当的时候重新排列命令列表。命令列表通过命令对象内的命令计数位进行排列,shell总是根据最近使用次数最多的命令排列在最前端,当shell空闲(即命令队列和输入输出缓冲区为空时)并且queue置位时,会尝试命令链表的重新排列(必须考虑排序算法带来的时间损耗)用户也可以选择命令重新排列失能,这种情况主要考虑用户使用的命令总是在一个很小的集合的情况,因为此时重新排序会带来比命令查询更大的损耗。
最重要的一个,shell拥有一个解析器,解析器用于对命令的解析。
shell拥有一个返回值成员,存放命令的返回值。

下面模拟一个
print ipaddr; if [ $? ne 192.168.1.1 ] setipaddr 192.168.1.1; tftp 0x30003000 zImage; else tftp 0x30003000 zImage endif
用户输入完后按下回车,即启动解析器。首先将print输入解析器,直到遇到一个空格时停止,解析器自动构造print字符串然后将其压入解析器的FIFO中。接着就会忽略接下来的所有空格,直到遇到ipaddr,于是解析器自动构造ipaddr字符串并且将其压入解析器的FIFO中,直到遇到‘;’分号,此时,解析器print作为命令名字查找得到命令对象,然后将ipaddr作为参数对命令的参数列表进行初始化,直到FIFO为空后参数链表初始化停止。如果命令不存在,或者参数不正确,则清空命令并打印一条错误提示。检查通过后解析器将初始化print命令对象并加入shell的命令队列当中。
接着扫描到 if,解析器自动构造if字符串然后将其压入FIFO,并且忽略接下来的符号直到遇见扫描到”[“符号,解析器构造并压入“[”字符串,之后将构造$?字符串,压入FIFO中,依次重复执行,直到遇见“endif”。这时侯解析器从FIFO中取出if作为命令名字,[]中包含的字符串 $? ne 192.168.1.1作为参数,接着取出“]”后面的setipaddr作为真子命令名字,192.168.1.1作为真子命令参数,取出else后面的tftp 作为伪子命令名字,0x30003000和zImage作为伪子命令参数,直到遇见endif时开始初始化if命令和两个子命令,并且将子命令加入if中对应的子命令链表,接着扫描,遇到回车符,扫描停止。 shell准备好相应的标志位后执行。执行完毕之后,shell检查命令执行的返回值并存入shell的返回值位,如果为真则调用真子命令,如果为假就调用伪子命令。

对 || 和 && 的支持: 假设 tftp 0x30003000 zImage && nand write 0x30003000 0 0x300000;
解析器顺序扫描全部压入FIFO,直到遇见;号,解析器顺序取出,tftp作为命令,查找得到命令对象,然后取出0x30003000和zImage作为参数初始化,再次取出得到&&,这时侯解析器将后一个字符串nand作为命令名字查找得到命令对象并且初始化,然后加入tftp的真子命令链表中。

对数值计算的支持:

    使用math关键字注明数值计算命令,解析器将式子转化为后缀表达式并后进行计算,shell内建加减乘除命令对数值计算进行支持,当然,内建命令是用户不可见的。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

0

暂无评论

评论前:需填写以下信息,或 登录

用户登录

忘记密码?