基于u-boot源码的简单shell软件实现
一、概述
1、shell概念
Shell(命令解析器),它用于接收用户输入的命令,进行解析,然后调用相应的应用程序,为使用者提供了使用软件的界面。
shell是操作系统最外面的一层。shell管理你与操作系统之间的交互:等待你输入,向操作系统解释你的输入,执行相应的应用程序,并且输出各种各样的处理结果。
2、shell分类
按照界面类型,可以分为图形界面shell和命令行式shell。
图形界面shell(Graphical User Interface shell 即 GUI shell),应用最为广泛的 Windows Explorer (微软的windows系列制作系统),还有也包括广为人知的 Linux shell,其中linux shell 包括 X window manger (BlackBox和FluxBox),以及功能更强大的CDE、GNOME、KDE、 XFCE。
命令行式shell(Command Line Interface shell ,即CLI shell),被广泛熟知的有bash / sh / ksh / csh(Unix/linux 系统)、cmd.exe(Windows XP 系统)、command.com(DOS系统)。
3、shell的运行模式
Shell的运行模式可以分为:交互式和非交互式。
交互式模式就是shell等待你的输入,并且执行你提交的命令。这种模式被称作交互式是因为shell与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。当你签退后,shell也终止了。
shell也可以运行在另外一种模式:非交互式模式。在这种模式下,shell不与你进行交互,而是读取存放在文件(shell script),并且执行其中的命令。当它读到文件的结尾,shell也就终止了。
二、shell软件功能需求分析
1、本文的开发环境
本文希望在单片机上运行这个shell程序,单片机可以是STM32、AVR等等,本文的测试是在S3C2440开发板上完成的。用户输入通常选用PC机的键盘,由于硬件运行平台是单片机,就选用串口进行交互数据的传输。软件开发环境选用linux系统下的arm-linux-gcc交叉编译工具链,该工具链功能强大,可配置性较集成开发环境尤其独到之处。
2、本文shell的基本功能要求
本文目的在于实现一个简单的shell,功能不要求很多,但是要求完全描绘出一个shell的工作原理和shell软件结构。有了这样的软件结构,再向shell里添加其他的功能,就好像做填空题一样。
简单的shell功能可支持的命令虽然很少,但是也要确定选择哪些命令比较合适。实现这样简单的命令最好不需要增添其他的外设,比如说硬盘、网卡,利用最小的单片机系统就能搞定。这样可以节省工作量,将主要精力集中到shell软件结构上,而不是具体命令的实现上。基于这样的考虑,本文选择echo(回显)、md(内存显示)和hello(打印“hello world”)三个命令作为测试。另外,还必须提供shell必备的命令help或者?(打印所有命令的帮助信息)。而且对于每一个命令,通过“help+命令”的输入打印单个命令的详细信息。
三、shell软件设计方案
在shell运行期间,无非涉及两个模块。一个模块是等待用户输入,并把用户输入的字符保存起来。另外一个模块,就是把之前保存的用户输入解析出来,并且根据解析到的命令找到对应的函数地址。再根据用户输入命令的参数,将参数传给这个函数地址,进行函数调用。
shell的核心是如何根据命令字符串,找到对应的函数地址,这是一个算法问题。因为命令字符串相对应着一个函数地址,需要将它们用一个数据结构包含在一起,所以也是一个数据结构的问题。
有什么样的数据结构,就有什么样的算法,设计数据结构成了关键。一个命令的结构体应该包含这样的内容:命令的名字、命令参数的最大个数、命令对应函数的地址、命令的简要帮助信息、命令的详细帮助信息。
有了命令数据结构,在设计一个命令的时候,就将这些命令的必要信息提供好,然后将这些信息填充到它对应的结构体变量中。最后,再将所有命名对应的结构体变量保存在一个数据段中。通过编译器产生的参数,我们可以掌握这个数据段的起始地址和结束地址,从而知道命令数据段的长度,进而知道命令的个数。只要我们知道这个数据段的起始地址,因为命令结构体的长度固定,我们就可以准确的遍历整个命令数据段,找到匹配的命令。
如果设计好这样的命令数据结构,再来思考如何实现根据命令字符串找到对应的函数地址,其实就是一个遍历命令数据段的问题。从命令数据段的开头,拿所要找的命令子妇产依次与命令数据段中的每个命令结构体进行比较,直到找到匹配的那个为止。找到了匹配的命令结构体,也就找到了命令字符串对应的调用函数地址。
四、shell软件实现
1、命令结构体
根据上一章节的分析,命令结构体的实现代码如下:
struct cmd_tbl_s {
char *name; /* Command Name */
int maxargs; /* maximum number of arguments */
int repeatable;/* autorepeat allowed?*/
/* Implementation function */
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *usage; /* Usage message (short) */
char *help; /* Help message (long) */
};
其中,核心成员是命令对应的函数指针cmd,cmd的参数有4个。第一个参数是当前函数指针对应的命令结构体的地址,传递这样的参数的好处是命令函数可以根据这个指针找到命令所有的信息,为程序拓展带来了方便。最后一个参数是一个字符型指针,保存了输入参数的存放地址,以供函数调用。
2、读取输入函数
读取输入函数名为readline,这个函数就是将用户的输入按照一定的格式存储到一个缓冲区console_buffer中,并且将用户的输入在返回到显示界面中。当用户输入Enter键的时候,这个函数就认为用户输入结束。
3、查找并执行命令的函数
此函数的函数名为run_cmmand,它通过调用查找命令函数find_cmd,将存入缓冲区console_buffer中的内容逐一与命令数据存储区中命令结构体的命令字符串比较。如果完全匹配,就调用命令结构体对应的函数,并传入参数。
五、shell软件后期完善
本文实现的简单shell软件,功能还有待补充,比如说使用环境变量保存用户配置、Flash管理等等。但是,由于本文已将shell框架搭好,再向其中添加其他的命令已经变得非常容易。只需要新建一个实现新命令的C源文件,然后将必要的头文件加入,再编写具体的命令实现代码。下一步再将新命令的信息填入到新命令对应的命令结构体变量中,重新编译执行即可。
参考资料:《u-boot-1.1.6 源码包》
附本文shell的实现代码:shell.zip
基于u-boot源码的简单shell软件实现的更多相关文章
- 曹工说Spring Boot源码(28)-- Spring的component-scan机制,让你自己来进行简单实现,怎么办
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下
写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 大 ...
- Spring Boot源码中模块详解
Spring Boot源码中模块详解 一.源码 spring boot2.1版本源码地址:https://github.com/spring-projects/spring-boot/tree/2.1 ...
- Spring Boot源码分析-启动过程
Spring Boot作为目前最流行的Java开发框架,秉承"约定优于配置"原则,大大简化了Spring MVC繁琐的XML文件配置,基本实现零配置启动项目. 本文基于Spring ...
- 曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(11)-- context:component-scan,你真的会用吗(这次来说说它的奇技淫巧)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(12)-- Spring解析xml文件,到底从中得到了什么(context:component-scan完整解析)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(13)-- AspectJ的运行时织入(Load-Time-Weaving),基本内容是讲清楚了(附源码)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(14)-- AspectJ的Load-Time-Weaving的两种实现方式细细讲解,以及怎么和Spring Instrumentation集成
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
随机推荐
- 垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
Delphi 是一个基本上被我遗忘的工具, 要不是在使用RapidSql , 我是收不到Embarcadero 公司发出的邀请来參加Delphi XE5的公布会的. 有人可能要问为什么是Embarca ...
- android92 aidl远程进程通信
05项目RemoteService.java package com.itheima.remoteservice; //05项目 import com.itheima.remoteservice.Pu ...
- secureCRT常用设置
一.快捷键: 1. ctrl + a : 移动光标到行首[常用] 2. ctrl + e :移动光标到行尾[常用] 3. ctrl + d :删除光标之后的一个字符 4. ctrl + w : 删除行 ...
- js操纵cookie技术
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...
- Android(java)学习笔记155:如何让你的GridView不再滚动
GridView显示不完整的原因是因为,他的外层也套用了一个滑动的控件,这个解决办法是:重写GridView,是控制GridView不能滚动,就是写一个类继承GridView 代码如下: publ ...
- Hibernate事务管理
User类: public class User implements Serializable{ public User(){} private Integer id; private String ...
- FWFT FIFO读操作注意
FWFT:First Word Fall Through的缩写,好像是Xilinx的说法,Altera对应的概念是Show-ahead synchronous(SASO).即数据在rdreq有效之前就 ...
- 【亲测可用】MySQL 4.1迁移到MySQL 5.0版本的中文乱码问题解决
核心:先导出结构,再导出数据. 结构最好使用myphpadmin导出.使用mysqldump导出的可能会导致一些问题. ---------------以下为转载---------------- 在生成 ...
- MySQL解压版安装配置详解
MySQL解压版安装起来比较简单,步骤相对较少.下面我们就来详细介绍一下如何在windows操作系统上安装解压班的MySQL. 1.下载解压版MySQL,地址:http://downloads.mys ...
- netMVC 搭建Ucenter 同步登陆退出discuz
先看一下效果