75-76-77 - Shell任务的实现

---- 整理自狄泰软件唐佐林老师课程

查看所有文章链接:(更新中)深入浅出操作系统 - 目录

文章目录

  • 1. 问题
  • 2. Shell任务简介
    • 2.1 实现Shell任务的关键
    • 2.2 思考
    • 2.3 解决方案设计
    • 2.4 事件机制的设计
  • 3. 模块重构
    • 3.1 Task模块重构
    • 3.2 Mutex模块重构
    • 3.3 编程实验:模块重构
    • 3.4 思考
  • 4. Shell实现流程
    • 4.1 关键问题
    • 4.2 解决方案
    • 4.3 解决方案实现
    • 4.4 编程实验:Shell任务的实现(主要是输入部分)
    • 4.5 思考
  • 5. Shell任务界面设计
    • 5.1 Shell任务的完善
    • 5.2 缓存用户输入
    • 5.3 删除键(Backspace)的支持
    • 5.4 回车键(Enter)的支持
    • 5.5 编程实验:Backspace & Enter
    • 5.6 命令映射设计
      • 5.6.1 命令注册
      • 5.6.2 未知命令入口函数
    • 5.7 编程实验:Shell任务的完善
    • 5.8 思考

1. 问题

  • 驱动键盘之后能做什么?

2. Shell任务简介

  • Shell的 本质是一个 任务(执行于用户态)
  • 简单的命令行用户界面
    • 提供用户与系统交互的接口
  • 命令解释器,解释用户输入的命令
    • 根据用户命令启动相应的系统功能

2.1 实现Shell任务的关键

  • 获取键盘输入的字符

75-76-77 - Shell任务的实现_第1张图片

2.2 思考

  • 当Shell请求用户输入时,用户是否正在输入字符?
    不一定正在输入字符 ==> shell任务等待 ==> 可执行态切换为等待状态
  • 当多个任务请求用户输入时,哪个任务应该获得输入的字符?

75-76-77 - Shell任务的实现_第2张图片

2.3 解决方案设计

  • 定义内核中 事件 的概念
  • 当任务请求输入时(调用ReadKey()时)产生事件
    • 事件产生:任务进入等待状态
    • 事件销毁:任务进入可执行状态
  • Task模块根据 事件描述 执行具体的调度动作
    • 如:操作哪一个等待队列

2.4 事件机制的设计

  • 事件定义:触发任务在 可执行态等待状态 之间切换的因素
    75-76-77 - Shell任务的实现_第3张图片

  • type:描述事件类型(为什么发生状态切换?)

    • 比如:
      • 命名KeyEvent,获取用户输入,用户并没有真的输入时进入等待的场景
      • 命名MutexEvent,由于获取互斥锁不成功而进入等待状态的场景
      • 命名TaskEvent,触发任务进入等待状态的事件
  • id:事件标识信息(调度的关键)

  • param1:事件参数(可选)

  • param2:事件参数(可选)

75-76-77 - Shell任务的实现_第4张图片
75-76-77 - Shell任务的实现_第5张图片
75-76-77 - Shell任务的实现_第6张图片

  • 事件 - 来统一任务需要等待的情况
    • 事件产生:进入等待
    • 再次进入可执行态:事件销毁

3. 模块重构

  • Task模块
    EventSchedule(action, event):根据事件执行调度
    WaitTask(name):通过事件让任务进入等待状态
  • Mutex模块
    为每个互斥锁增加一个等待队列
    无法获取锁的任务进入该锁的等待队列

3.1 Task模块重构

75-76-77 - Shell任务的实现_第7张图片

  • 不同事件不同处理
    75-76-77 - Shell任务的实现_第8张图片

3.2 Mutex模块重构

75-76-77 - Shell任务的实现_第9张图片

3.3 编程实验:模块重构

【参看链接】:75-76-77 - Shell任务的实现 / 75

75-76-77 - Shell任务的实现_第10张图片

3.4 思考

  • Shell任务如何实现?系统调用uint ReadKey()如何实现?

4. Shell实现流程

用户界面 - 交互 - 输入命令
75-76-77 - Shell任务的实现_第11张图片

4.1 关键问题

  • 当Shell请求用户输入时,用户是否正在输入字符?
    • 大概率此时用户并没有正在输入 ==> 等待
  • 当多个任务请求用户输入时,哪个任务应该获得输入的字符?
    • 每个任务都应该获得输入

4.2 解决方案

75-76-77 - Shell任务的实现_第12张图片

4.3 解决方案实现

75-76-77 - Shell任务的实现_第13张图片
75-76-77 - Shell任务的实现_第14张图片

4.4 编程实验:Shell任务的实现(主要是输入部分)

【参看链接】:75-76-77 - Shell任务的实现 / 76

75-76-77 - Shell任务的实现_第15张图片

4.5 思考

  • 如何实现Shell任务的用户接口功能? – 交互

5. Shell任务界面设计

75-76-77 - Shell任务的实现_第16张图片

5.1 Shell任务的完善

  • 支持 删除键(Backspace)和 回车键(Enter)
    • Backspace:修改已输入命令中的字符
    • Enter:确认命令输入完毕
  • 命令类型
    • 启动型命令 - 启动任务
    • 应用级命令 - 由shell实现,如clean
    • 内核级命令 - shell依赖系统调用

5.2 缓存用户输入

  • 思考:用户输入存储在哪?
    • 定义全局字符缓冲区 gKBuf
    • 存储用户输入的字符
    • 定义全局变量 gKIndex
    • 记录新字符在缓冲区中的位置

75-76-77 - Shell任务的实现_第17张图片

5.3 删除键(Backspace)的支持

  1. 从后向前删除命令行字符
  2. 删除字符后光标回退到上一个位置
  3. 获取PROMPT(即下图中的“D.T.OS >> ”打印)的长度
    75-76-77 - Shell任务的实现_第18张图片
  4. 获取当前光标横坐标
    • 当光标横坐标大于PROMPT长度时:
      • 将光标前一个位置输出空格
      • 将光标移动到前一个位置

75-76-77 - Shell任务的实现_第19张图片

5.4 回车键(Enter)的支持

  1. 在字符缓冲区gKBuf中添加 0结束符
  2. 执行命令对应的功能
    75-76-77 - Shell任务的实现_第20张图片

5.5 编程实验:Backspace & Enter

【参看链接】:75-76-77 - Shell任务的实现 / 77 / 00BackspaceAndEnter

75-76-77 - Shell任务的实现_第21张图片

5.6 命令映射设计

命令字符串功能(入口函数) 之间的映射

  • 将命令和命令入口进行映射(命令注册
    1. 用户输入命令后,查找命令入口并执行
    2. 无法找到命令入口时,执行无效命令入口

75-76-77 - Shell任务的实现_第22张图片

5.6.1 命令注册

75-76-77 - Shell任务的实现_第23张图片

5.6.2 未知命令入口函数

75-76-77 - Shell任务的实现_第24张图片

5.7 编程实验:Shell任务的完善

【参看链接】:75-76-77 - Shell任务的实现 / 77 / 01命令映射

75-76-77 - Shell任务的实现_第25张图片

5.8 思考

  • 内核级命令如何实现?

你可能感兴趣的:(深入浅出操作系统,linux,unix,shell,C,task)