自制操作系统Antz day11——实现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>");
}

目录
相关文章
|
2月前
|
Shell Linux 程序员
【Linux】Shell 命令以及运行原理
【Linux】Shell 命令以及运行原理
|
10天前
|
存储 Shell 数据安全/隐私保护
Shell 内建命令:Shell 的内在魔力
Shell 内建命令比外部命令执行快,不需额外进程。`type` 命令用来检查命令类型。内建命令如 `cd`、`alias` 和 `echo` 直接在 Shell 中执行,不涉及磁盘 I/O。`type` 示例展示了 `cd` 是内建的,`ifconfig` 是外部的。`bash` 包含多种内建命令,如 `cd` 用于切换目录,`alias` 定义别名,`read` 从输入读取数据。`echo` 默认加换行,`echo -n` 可避免。
19 5
|
9天前
|
Shell 虚拟化
分布式系统详解--框架(Zookeeper-基本shell命令)
分布式系统详解--框架(Zookeeper-基本shell命令)
12 1
|
12天前
|
安全 Shell Linux
探索Linux命令chsh:更改用户的默认shell
`chsh`是Linux命令,用于更改用户的默认登录shell。它涉及用户环境配置和系统安全,允许用户选择更适合自己的shell以提升效率。命令有交互式选项和参数如`-s`来指定新shell。在使用时要注意新shell的可执行性、权限问题及选择合适的shell。例如,要更改为bash,用户可运行`chsh`后按提示操作,而root用户能用`sudo chsh -s /bin/zsh john`为用户`john`设定zsh。在更改前,确认shell路径、权限,并了解不同shell的特点。
|
24天前
|
运维 安全 Unix
Linux操作系统 , 常用命令
Linux操作系统 , 常用命令
|
9天前
|
分布式计算 Hadoop Shell
分布式系统详解--框架(Hadoop-基本shell命令)
分布式系统详解--框架(Hadoop-基本shell命令)
8 0
|
12天前
|
Shell Perl
7操作系统基础-Shell编程
7操作系统基础-Shell编程
7 0
|
13天前
|
Shell
Shell [[]] 命令:条件判断的升级版
`[[ ]]` 是 Bash 中增强型的条件判断命令,提供比 `[ ]` 更多的灵活性,如无需引号包裹变量、直接字符串比较及正则支持。例如: ```markdown - 不加引号比较:`[[ -z $str1 ]]` - 逻辑运算:`[[ -z $str1 ]] || [[ -z $str2 ]]` - 正则匹配:`[[ $phone =~ ^1[0-9]{10}$ ]]` ``` 它不支持 `-a` 和 `-o`,但能用 `&&` 和 `||` 进行逻辑操作。用于复杂字符串验证和文件处理时非常有用。
16 0
|
13天前
|
Shell Windows
Shell test [] 命令:条件判断的艺术
`test` 命令在Shell脚本中用于条件检测,涉及数值、字符串和文件比较。例如,`test $a -eq $b` 检查两个数是否相等;`-e` 检查文件是否存在;`-w` 检查文件是否可写。数值比较不支持 `&gt;=` 和 `&lt;=`,需用 `-ge` 和 `-le`。字符串比较时注意空值,使用双引号。逻辑运算包括 `-a`(与)、`-o`(或)和 `!`(非)。文件类型和权限检测也是`test`的重要用途。
12 0
|
17天前
|
Linux Shell 程序员
【Linux操作系统】命令的运行原理
【Linux操作系统】命令的运行原理

热门文章

最新文章