zoukankan      html  css  js  c++  java
  • 自制操作系统Antz(11)——实现shell(下)命令响应

    我已经规范了系统代码风格,类似于按照linux分包,把各部分功能区分开了

    Antz系统更新地址

    Linux内核源码分析地址

    Github项目地址

    在之前的任务中,我们已经通过直接操作显卡驱动完成了简单的图形化。

    需要了解之前的部分:

    直接操作显卡请参考day03

    简单图形化的实现请参考day09

    键盘按键中断响应请参考day10

    Makefile

    项目目录

    s

    一 . 如何实现命令缓存

    在之前已经完成了键盘的响应工作,但这种响应却是有很大的问题,比如说对于一次按键的两次中断处理。后来我把两种中断都加入了响应判断中,这样就不会有之前第10天所提到的bug了。

    * 在替换函数中完成识别。修改如下

    char* replace_char(char s[40]){
    	char *chr = "$" ;
    	if((strcmp(s,"1E")==0)||(strcmp(s,"9E")==0)){
    			chr = "a" ;
    	}else if((strcmp(s,"30")==0)||(strcmp(s,"B0")==0)){
    			chr = "b" ;
    	}
    	... // 省略
    	return chr ;
    

    * 这里是一些功能按键的识别修改

        // Enter  -> 回车键 响应之前缓存的命令 换行
    	if((strcmp(s,"1C")==0)||(strcmp(s,"9C")==0)){
    			action_command(binfo);  //响应命令
    			write_x = 58 ;   //下面是换行
    			write_y += 19 ;
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
    	} 
        // F1 -> 终端刷新  类似于clear命令
    	else if((strcmp(s,"3B")==0)||(strcmp(s,"BB")==0)){  //关于F1的响应中断
    			sprintf(command,"%s","");  // 命令缓存清空
    			flag = 0 ;  // 按键模式回复默认,这个看第10天,本质目的是为了处理一次按键的两次终端
    			new_pe(binfo);  // 通过操作显存直接刷新当前终端
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
    	}
    	//  Backspace -> 删格键
    	else if(strcmp(s,"0E")==0){
    			// 回退
    			write_x -= 8 ;
    			boxfill8(binfo->vram, binfo->scrnx , COL8_000000,  write_x,     write_y,     write_x+19, write_y+19);
    			if(write_x<=58){
    				write_x = 146 ;
    				write_y -= 19 ;
    			}
    	} 
    

    这些就是按键识别上目前修改的内容了。

    接下来我们要添加一个功能,在每次按键之后,不但在屏幕上显示这个键,而且将他缓存在缓冲区,在下次回车的时候进行识别,并清空。

    先来看一个简单的demo

    // command数组就是命令缓存区
    char  command[100]  = "";
    
    void add_command(char *s)  { 
        sprintf(command,"%s%s",command,s); 
    }
    
    void action_command(){
        // 响应
    }
    
    

    二 . 实现

    command就是一个命令缓存数组,每次按键之后调用add_command()命令将这次的按键保存。

    sprintf()这个函数是字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。sprintf 是个变参函数。使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。

    我们使用sprintf函数直接在command后面添加了s字符。

    那么在下次按下Enter的时候,我们只需要调用action_command,并且在里面识别是什么命令,然后做出合适的响应即可。

    来看看完整的命令缓冲区实现。

    // 指令缓存,但是因为中断响应的时间问题,终端输入速度要非常慢
    char  command[100]  = "";
    void add_command(char *s)  {
            
        if(strcmp(s," ")==0){
    	    sprintf(command,"%s%s",command,"");
        }else if(strcmp(s,"$")){
    		//忽略这种错误输入
    	}else {
    	    sprintf(command,"%s%s",command,s);  
    	} 
    }
    
    void action_command(struct BOOTINFO *binfo){
    		// action command 响应命令
    		// ls命令
    		// data命令
    		if(strcmp(command,"data")==0){
    			// get new data;
    			write_y += 19 ;
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS in 2018");
    		}else if(strcmp(command,"cls")==0){
    			flag = 0 ;
    			new_pe(binfo);
    		}else if(strcmp(command,"version")==0){
    			write_y += 19 ;
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Antz.version.1.1");
    		}else if(strcmp(command,"help")==0){
    			// help内容过多,显示在图形化界面区域
    			
    		}else if(sizeof(command)>=1){
    				write_y += 19 ;
    				putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Not Found");
    		}
    		// 命令缓存清除
    		sprintf(command,"%s","");
    }
    
    

    现在使用Makefile来生成这个支持命令的img镜像。

        make img
    

    使用虚拟机打开镜像,结果如下

    os

    终端主要代码如下:

    
    int write_x = 55 ;
    int write_y = 57 ;
    
    char* replace_char(char s[40]){
    	char *chr = "$" ;
    	if((strcmp(s,"1E")==0)||(strcmp(s,"9E")==0)){
    			chr = "a" ;
    	}else if((strcmp(s,"30")==0)||(strcmp(s,"B0")==0)){
    			chr = "b" ;
    	}else if((strcmp(s,"2E")==0)||(strcmp(s,"AE")==0)){
    			chr = "c" ;
    	}else if((strcmp(s,"20")==0)||(strcmp(s,"A0")==0)){
    			chr = "d" ;
    	}else if((strcmp(s,"12")==0)||(strcmp(s,"92")==0)){
    			chr = "e" ;
    	}else if((strcmp(s,"21")==0)||(strcmp(s,"A1")==0)){
    			chr = "f" ;
    	}else if((strcmp(s,"22")==0)||(strcmp(s,"A2")==0)){
    			chr = "g" ;
    	}else if((strcmp(s,"23")==0)||(strcmp(s,"A3")==0)){
    			chr = "h" ;
    	}else if((strcmp(s,"17")==0)||(strcmp(s,"97")==0)){
    		chr = "i" ;
    	}else if((strcmp(s,"24")==0)||(strcmp(s,"A4")==0)){
    		chr = "j" ;
    	}else if((strcmp(s,"25")==0)||(strcmp(s,"A5")==0)){
    		chr = "k" ;
    	}else if((strcmp(s,"26")==0)||(strcmp(s,"A6")==0)){
    		chr = "l" ;
    	}else if((strcmp(s,"32")==0)||(strcmp(s,"B2")==0)){
    		chr = "m" ;
    	}else if((strcmp(s,"31")==0)||(strcmp(s,"B1")==0)){
    		chr = "n" ;
    	}else if((strcmp(s,"18")==0)||(strcmp(s,"98")==0)){
    		chr = "o" ;
    	}else if((strcmp(s,"19")==0)||(strcmp(s,"99")==0)){
    		chr = "p" ;
    	}else if((strcmp(s,"10")==0)||(strcmp(s,"90")==0)){
    		chr = "q" ;
    	}else if((strcmp(s,"13")==0)||(strcmp(s,"93")==0)){
    		chr = "r" ;
    	}else if((strcmp(s,"1F")==0)||(strcmp(s,"9F")==0)){
    		chr = "s" ;
    	}else if((strcmp(s,"14")==0)||(strcmp(s,"94")==0)){
    		chr = "t" ;
    	}else if((strcmp(s,"16")==0)||(strcmp(s,"96")==0)){
    		chr = "u" ;
    	}else if((strcmp(s,"2F")==0)||(strcmp(s,"AF")==0)){
    		chr = "v" ;
    	}else if((strcmp(s,"11")==0)||(strcmp(s,"91")==0)){
    		chr = "w" ;
    	}else if((strcmp(s,"2D")==0)||(strcmp(s,"AD")==0)){
    		chr = "x" ;
    	}else if((strcmp(s,"15")==0)||(strcmp(s,"95")==0)){
    		chr = "y" ;
    	}else if((strcmp(s,"2C")==0)||(strcmp(s,"AC")==0)){
    		chr = "z" ;
    	}else if((strcmp(s,"39")==0)||(strcmp(s,"B9")==0)){
    		chr = " " ;
    	}
    	return chr ;
    }
    
    int flag = 1 ;
    
    // 指令缓存,但是因为中断响应的时间问题,终端输入速度要非常慢
    char  command[100]  = "";
    void add_command(char *s)  {
    /*
    if(strcmp(s," ")==0){
    	sprintf(command,"%s%s",command,"");
    }else	if(strcmp(s,"$")){
    				//忽略这种错误输入
    		}else {
    	}
    */
    		sprintf(command,"%s%s",command,s);
    
    }
    
    void action_command(struct BOOTINFO *binfo){
    		// action command
    		// ls
    		// data
    		if(strcmp(command,"data")==0){
    			// get new data;
    			write_y += 19 ;
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS in 2018");
    		}else if(strcmp(command,"cls")==0){
    			flag = 0 ;
    			new_pe(binfo);
    		}else if(strcmp(command,"version")==0){
    			write_y += 19 ;
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Antz.version.1.1");
    		}else if(strcmp(command,"help")==0){
    			// help内容过多,显示在图形化界面区域
    		}else if(sizeof(command)>=1){
    				write_y += 19 ;
    				putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Not Found");
    		}
    		// 命令缓存清除
    		sprintf(command,"%s","");
    }
    
    void key(struct BOOTINFO *binfo,char s[40]){
    	if((strcmp(s,"1C")==0)||(strcmp(s,"9C")==0)){
    			action_command(binfo);
    			write_x = 58 ;
    			write_y += 19 ;
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
    	}else if((strcmp(s,"3B")==0)||(strcmp(s,"BB")==0)){  //关于F1的响应中断
    			sprintf(command,"%s","");
    			flag = 0 ;
    			new_pe(binfo);
    			putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
    	}else if(strcmp(s,"0E")==0){
    			// 回退
    			write_x -= 8 ;
    			boxfill8(binfo->vram, binfo->scrnx , COL8_000000,  write_x,     write_y,     write_x+19, write_y+19);
    			if(write_x<=58){
    				write_x = 146 ;
    				write_y -= 19 ;
    			}
    	}else {
    			//putfonts8_asc(binfo->vram, binfo->scrnx,  write_x,  write_y, COL8_FFFFFF, s);
    			putfonts8_asc(binfo->vram, binfo->scrnx,  write_x,  write_y, COL8_FFFFFF, replace_char(s));
    			add_command(replace_char(s));
    			write_x += 8 ;
    			// 添加响应区
    			//清除
    			//boxfill8(binfo->vram, binfo->scrnx, COL8_008400 , 300	,240	,310	,250);
    			//打印字符 Only use debug
    			//putfonts8_asc(binfo->vram, binfo->scrnx,  300,  240 ,COL8_000000, s) ;
    	}
    	if(write_x>148){
    		write_x = 58 ;
    		write_y += 19 ;
    		//putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>");
    	}
    	if(write_y>180){
     		new_pe(binfo);
    		putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
    	}
    
    }
    
    void main(void)
    {
    	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
    	char s[40], mcursor[256], keybuf[32], mousebuf[128];
    	int mx, my, i;
    
    	init_gdtidt();
    	init_pic();
    	io_sti(); /* PIC的初始化已经完成*/
    
    	fifo8_init(&keyfifo, 32, keybuf);
    	fifo8_init(&mousefifo, 128, mousebuf);
    	io_out8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */
    	io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */
    
    	init_keyboard();
    
    	init_palette();
    	init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
    
    	putfonts8_asc(binfo->vram, binfo->scrnx,  0,  0, COL8_FFFFFF, "Terminal-Antz");
    	putfonts8_asc(binfo->vram, binfo->scrnx,  0,  0, COL8_000000, "Terminal-Antz");
    	putfonts8_asc(binfo->vram, binfo->scrnx,  107,  0, COL8_000000, "|-|o|x|");
    	putfonts8_asc(binfo->vram, binfo->scrnx, 4, 19, COL8_FFFFFF, "AntzOS> SayHello()");
    	putfonts8_asc(binfo->vram, binfo->scrnx, 4, 38, COL8_FFFFFF, "Hello My AntzOs.");
    	putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>_");
    
     
    	for (;;) {
    		io_cli();
    		if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
    			io_stihlt();
    		} else {
    			if (fifo8_status(&keyfifo) != 0) {
    
    				i = fifo8_get(&keyfifo);
    				io_sti();
    				sprintf(s, "%02X", i);
    				if (flag){
    					key(binfo,s);
    				}
    				if(flag==1){
    					flag = 0 ;
    				}else {
    					flag = 1 ;
    				}
    			}  
    		}
    	}
    }
    
    void new_pe(struct BOOTINFO *binfo){
    	write_x = 58 ;
    	write_y = 19 ;
    	// 右边并没有保存
    	init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
    	putfonts8_asc(binfo->vram, binfo->scrnx,  0,  0, COL8_FFFFFF, "Terminal-Antz");
    	putfonts8_asc(binfo->vram, binfo->scrnx,  0,  0, COL8_000000, "Terminal-Antz");
    	putfonts8_asc(binfo->vram, binfo->scrnx,  107,  0, COL8_000000, "|-|o|x|");
    	// 此处保留此输出,交给调用者自己
    	//	putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
    }
    
    
    
  • 相关阅读:
    VS2012 Unit Test(Void, Action, Func) —— 对无返回值、使用Action或Func作为参数、多重载的方法进行单元测试
    string中Insert与Format效率对比、String与List中Contains与IndexOf的效率对比
    VS2012 Unit Test —— 我对接口进行单元测试使用的技巧
    委托又给我惹麻烦了————记委托链的取消注册、获取返回值
    委托的N种写法,你喜欢哪种?
    VS2012 单元测试之泛型类(Generics Unit Test)
    Unity V3 初步使用 —— 为我的.NET项目从简单三层架构转到IOC做准备
    使用NuGet助您玩转代码生成数据————Entity Framework 之 Code First
    JqueryEasyUI浅谈---视频教程公布
    JqueryEasyUI浅谈本地化应用
  • 原文地址:https://www.cnblogs.com/LexMoon/p/antz11.html
Copyright © 2011-2022 走看看