3.3 内部命令的处理过程
对于内部命令,当前的实现十分简单,只是通过定义一个内部命令数组把内部命令的命令字符串和处理函数关联起来。代码如下。
#define CMD_OBJ_NUM 18 __CMD_OBJ CmdObj[CMD_OBJ_NUM]={ {"version" , VerHandler}, {"memory" , MemHandler}, {"sysinfo" , SysInfoHandler}, {"sysname" , SysNameHandler}, {"help" , HlpHandler}, {"date" , DateHandler}, {"time" , TimeHandler}, {"cpuinfo" , CpuHandler}, {"support" , SptHandler}, {"runtime" , RunTimeHandler}, {"test" , TestHandler}, {"untest" , UnTestHandler}, {"memview" , MemViewHandler}, {"sendmsg" , SendMsgHandler}, {"ktview" , KtViewHandler}, {"ioctrl" , IoCtrlApp}, {"sysdiag" , SysDiagApp}, {"cls" , ClsHandler} }; 其中__CMD_OBJ是预先定义的一个结构体,代码如下。 struct __CMD_OBJ{ LPSTR CmdStr; //Command text. __CMD_HANDLER CmdHandler; //Command handler. };
这样,Hello China在实现内部命令的时候,只需要编写一个处理函数(该函数的原型应该是__CMD_HANDLER定义的一个只接受字符串作为参数,并返回VOID的函数),并在上述数组中增加一项即可。
DoCommand函数首先处理内部命令,处理过程如下。
① 以用户输入的命令字符串为索引,依次检索上述数组,若能够找到一个合适的,则采用用户输入的命令参数(字符串)为参数,调用该函数;
② 若上述查找过程失败,即上述数组中不存在与用户输入对应的字符串,则会进入外部命令处理阶段。
需要说明的是,用户的输入被操作系统按照“命令字符串 参数1参数2 ……”的形式解释,即用户按下回车键后,操作系统会把整个字符串传递给DoCommand函数,DoCommand函数则提取字符串前面的命令部分(命令字符串),然后把后面的参数部分作为参数,传递给命令处理函数。按照目前的实现,命令字符串跟参数之间是通过空格的方式分隔的,但命令字符串也有一个最大长度,即32字节,比如,假设用户输入下列字符串后按下回车。
[system-view]thisismycommandthisismycommandthis hello china <ENTER>
则命令字符串会被截取为“thisismycommandthisismycommandth”,因为命令字符串超过了32位。另外,在调用该命令的处理函数时,传递的参数将是“hello china”。
下面我们以实现一个内部命令为例,说明内部命令的实现方式。
① 假设实现的内部命令为mycommand,首先编写一个内部命令的功能函数,可以直接在SHELL.CPP文件中添加,也可以通过另外的模块实现,然后在SHELL.CPP中,包含实现的命令函数的头文件。假设mycommand命令的实现函数如下。
VOID mycommand(LPSTR) { ChangeLine(); PrintLine("Hello,World!"); ChangeLine(); }
该函数的功能十分简单,打印出“Hello,World!”字符串,这也是大多数编程语音的一个入门示例。
② 把该命令字符串和命令函数添加到内部命令列表中,并更改CMD_OBJ_NUM宏为原来的值加一,因为新增加了一个内部命令。代码如下。
//#define CMD_OBJ_NUM 18 #define CMD_OBJ_NUM 19 __CMD_OBJ CmdObj[CMD_OBJ_NUM]={ {"version" , VerHandler}, {"memory" , MemHandler}, {"sysinfo" , SysInfoHandler}, {"sysname" , SysNameHandler}, {"help" , HlpHandler}, {"date" , DateHandler}, {"time" , TimeHandler}, {"cpuinfo" , CpuHandler}, {"support" , SptHandler}, {"runtime" , RunTimeHandler}, {"test" , TestHandler}, {"untest" , UnTestHandler}, {"memview" , MemViewHandler}, {"sendmsg" , SendMsgHandler}, {"ktview" , KtViewHandler}, {"ioctrl" , IoCtrlApp}, {"sysdiag" , SysDiagApp}, {"mycommand", mycommand}, {"cls" , ClsHandler} };
③ 重新编译连接(rebuild)整个操作系统核心,并重新制作引导盘引导系统。成功启动后,在命令行提示符下,输入mycommand并按回车键,就可以看到mycommand的输出了。