Shell

什么是Shell

Shell是壳的意思,计算机中Shell常用于表示一种命令行的用户操作接口,Shell常用来表示封装,由于计算机很复杂,所以常把功能的实现和调用分开,Shell里边是功能实现,外边是功能调用,所以Shell可以看做是复杂功能实现的封装并向外部提供的比较容易的而接口

程序或者操作系统的接口

程序或者操作系统在运行起来之后,都会为用户提供操作界面,该界面就是一种Shell,用户通过该Shell来调用操作系统内部的实现功能,Shell编程就指的是在Shell的层次上进行编程,基于Shell编程相对于语言编程比较容易一些,例如Win中的bat批处理或者Linux的脚本编程

GUI和CMD的Shell

GUI图形用户界面的Shell,用户体验比较友好,操作比较简单,易学易用,适合使用程序或者操作系统来工作的人,CMD相对比较麻烦,譬如Linux的终端或者Win中的CMD命令行界面,使用起来有点门槛,但是可以进行方便的Shell编程,适合做开发的人员

Shell运行原理

命令行的Shell运行原理,实际上是一个死循环,其中包含三部分,分别是命令接收,解析,执行串联的循环,命令行有标准的命令集,用户操作时必须知道操作需要通过哪个命令来实现,如果随便输入的命令不是标准命令集中的一个,则会提示用户命令不合法,让用户重新输入,用户输入命令的界面是命令行界面,需用户输入一行命令才能生效,常见的uboot就是一个裸机Shell,Linux终端和Win的CMD就是一个命令行Shell,Win,ubuntu以及Android的图形界面就是图形界面的Shell

Shell编程

先写一个简单的PC上的Shell小程序

简单的Shell程序模仿

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LEN 256
#define MAX_CMD_LEN 3

// 定义标准命令
#define led "led"
#define lcd "lcd"
#define pwm "pwm"

// 最多支持命令数
char cmdset[MAX_CMD_LEN][MAX_LINE_LEN];

// 初始化命令集函数
void init_cmd_set(void) {
    memset(cmdset,0,sizeof(cmdset));
    strcpy(cmdset[0],led);
    strcpy(cmdset[1],lcd);
    strcpy(cmdset[2],pwm);
}

int main(void) {
    // 初始化命令集
    init_cmd_set();
    // 开启死循环
    while(1) {
        // 先打印命令行提示符
        printf("Welcome:");
        // 存放用户的输入内容
        char str[MAX_LINE_LEN];
        // 清空数组
        memset(str,0,sizeof(str));
        // 获取用户输入
        scanf("%s",str);
        // 解析用户输入的命令
        int i;
        // 遍历命令集
        for(i = 0;i < MAX_CMD_LEN;i++) {
            // 查看是否是命令集中的命令
            if(!strcmp(str,cmdset[i])) {
                // 找到了命令,需要执行
                printf("%s\n",str);

                printf("%s\n","processing cmd...");

                //执行完退出
                break;
            }
        }
        // 没找到对应的命令
        if(i >= MAX_CMD_LEN) {
            // 提示用户没有该命令
            printf("%s is a valid command,please input the correct commamd!\n",str);
        }
    }
    return 0;
}

移植ShellDemo到开发板

我们把原来写的uart的例子和上节课写的demo结合在一起,可以得到一个开发板上运行的ShellDemo:

#include "stdio.h"
#include "uart.h"

void memset(char *p,int val,int length) {
    int i;
    for(i = 0;i < length; i++) {
        p[i] = val;
    }
}

int main(void) {
    char buf[100] = {0};
    uart_init();

    puts("shell:\n");
    while(1) {
        puts("someone#");
        memset(buf,0,sizeof(buf));
        gets(buf);
        puts("您输入的是: ");
        puts(buf);
        puts("\n");
    }
    return 0;
}

定义命令集

把Demo中定义的命令移植过来,可以实现一个命令的程序:

#include "cmd.h"
#include "stdio.h"
#include "string.h"

#define MAX_LINE_LEN 256
#define MAX_CMD_LEN 3

// 定义标准命令
#define led "led"
#define lcd "lcd"
#define pwm "pwm"

// 最多支持命令数
char cmdset[MAX_CMD_LEN][MAX_LINE_LEN];

// 初始化命令集函数
void init_cmd_set(void) {
    memset((char *)cmdset,0,sizeof(cmdset));
    strcpy(cmdset[0],led);
    strcpy(cmdset[1],lcd);
    strcpy(cmdset[2],pwm);
}

// 解析命令
int cmd_parser(char *cmd) {
        // 解析用户输入的命令
    int i;
    // 遍历命令集
    for(i = 0;i < MAX_CMD_LEN;i++) {
        // 查看是否是命令集中的命令
        if(!strcmp(cmd,cmdset[i])) {
            // 找到了命令,需要执行
            puts(cmd);

            puts("processing cmd...");

            //执行完退出
            break;
        }
    }
    // 没找到对应的命令
    if(i >= MAX_CMD_LEN) {
        // 提示用户没有该命令
        puts("not a valid command,please input the correct commamd!\n");
    }

    return 0;
}

//执行命令
void cmd_exec(void) {

}

然后在main函数中就可以调用这些函数来分析和处理命令:

#include "stdio.h"
#include "uart.h"
#include "cmd.h"
#include "string.h"

int main(void) {
    char buf[100] = {0};
    init_cmd_set();
    uart_init();

    puts("shell:\n");
    while(1) {
        puts("someone#");
        memset(buf,0,sizeof(buf));
        gets(buf);
        // 解析命令
        cmd_parser(buf);
        // 执行命令
        cmd_exec();
    }
    return 0;
}

添加命令

我们最开始添加了三个命令,led,lcd和pwm,但是都不是真是的命令,并没有实际的执行,我们需要把这些命令真实的运行起来,最终我们的命令代码如下所示:

#include "cmd.h"
#include "stdio.h"
#include "string.h"
#include "led.h"
#include "pwm.h"
#include "lcd.h"
#include "adc.h"

#define MAX_LINE_LEN 256
#define MAX_CMD_LEN 4

#define CMD_ARGS 2
#define CMD_ARGS_LEN 20

// 定义标准命令
#define led "led"
#define lcd "lcd"
#define pwm "pwm"
#define adc "adc"

// 最多支持命令数
char cmdset[MAX_CMD_LEN][MAX_LINE_LEN];

char acmd[CMD_ARGS][CMD_ARGS_LEN];

int cmd_index = -1;

// 初始化命令集函数
void init_cmd_set(void) {
    memset((char *)cmdset,0,sizeof(cmdset));
    memset((char *)acmd,0,sizeof(acmd));
    strcpy(cmdset[0],led);
    strcpy(cmdset[1],lcd);
    strcpy(cmdset[2],pwm);
    strcpy(cmdset[3],adc);
}

// 解析命令
int cmd_parser(char *cmd) {
    // 解析用户输入的命令
    cmd_split(acmd,cmd);

    int i;

    cmd_index = -1;
    // 遍历命令集
    for(i = 0;i < MAX_CMD_LEN;i++) {
        // 查看是否是命令集中的命令
        if(!strcmp(acmd[0],cmdset[i])) {
            // 找到了命令,需要执行
            cmd_index = i;
            break;
        }
    }
    return 0;
}

void handle_led() {
    led_init();
    if (!strcmp(acmd[1],"on")) {
        led_on();
    } else if (!strcmp(acmd[1],"off")) {
        led_off();
    } else {
        puts("use 'led on' or 'led off' to switch the led mode!\n");
    }
}

void handle_lcd() {
    lcd_init();
    if (!strcmp(acmd[1],"draw")) {
        draw_ascii_ok(500,306,GREEN,"Hello");
    } else {
        puts("use 'lcd draw' to draw some words!\n");
    }
}

void handle_adc() {
    adc_init();
    if (!strcmp(acmd[1],"collect")) {
        adc_collect();
    } else {
        puts("use 'adc collect' to switch the adc mode!\n");
    }
}

void handle_pwm() {
    timer2_pwm_init();
    if (!strcmp(acmd[1],"on")) {
        timer2_pwm_start();
    } else if (!strcmp(acmd[1],"off")) {
        timer2_pwm_stop();
    } else {
        puts("use 'pwm on' or 'pwm off' to switch the pwm mode!\n");
    }
}


//执行命令
void cmd_exec(void) {
    switch (cmd_index) {
    case 0:
        // 处理led
        handle_led();
        break;
    case 1:
        // 处理lcd
        handle_lcd();
        break;
    case 2:
        // 处理pwm
        handle_pwm();
        break;
    case 3:
        // 处理adc
        handle_adc();
        break;
    default:
        puts("not a valid command,please input the correct commamd!\n");
        break;
    }
}

如果要详细操作这些硬件,或者增加控制命令,可以根据实现代码增添即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值