HNU-2024操作系统实验-Lab9-Shell

news2024/9/9 5:20:23

一、 实验目的

  1. 理解Shell程序的原理、底层逻辑和Shell依赖的数据结构等

  2. 在操作系统内核MiniEuler上实现一个可用的Shell程序

  3. 能够根据相关原理编写一条可用的Shell指令

二、 实验过程

首先从底层出发,实现Shell程序

1.在src/include目录下新建prt_shell.h头文件:

在这里插入图片描述

这个板块中主要定义了shell能够显示的最大长度以及文件路径的最大值,然后定义了ShellCB控制块,用于Shell的管理,其中包含对用户输入、输入命令的历史的管理以及维护当前工作目录等,此处的ShellBuf是作为Shell的缓冲区,输入的指令会存放在缓冲区内,经过解析得到最终应该执行的操作。

2.向src/bsp目录下的print.c文件中的PRT_UartInit 添加初始化代码,使其支持接收数据中断。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

由于我们的操作系统内核MiniEuler不能使用标准输入输出流,所以需要通过串口交互的方式来实现往Shell的缓冲区中写入字符,在此板块中首先定义了一系列串口的配置位和掩码,如:TXE是串口的第9位(从0开始),在实验二中也进行过类似的操作,接着定义了一个用于UART串口接收数据时使用的信号量sem_uart_rx,最后进行串口的初始化,首先禁用UART,清空中断状态,设定中断mask(允许接收中断),并设置波特率相关寄存器(UARTIBRD和UARTFBRD)。

然后读取Line Control Register(LCR)的当前配置,将其与一组掩码进行或操作来设置数据位、奇偶校验和停止位的配置,然后写回寄存器。这里使用的配置是8个数据位、无奇偶校验、1个停止位,并启用FIFO。最后通过设置控制寄存器(UART Control Register)来启用UART,并使能接收和发送。串口配置完成后,调用OsGicIntSetConfig,OsGicIntSetPriority,OsGicClearInt,OsGicEnableInt函数来配置UART接收中断,最后创建数据接收信号量。

3.在src/bsp目录中的print.c文件中实现 OsUartRxHandle()处理接收中断

在这里插入图片描述

该中断处理函数首先读取UART的状态寄存器,然后检查flag中的第4位(接收FIFO空标志)是否为0,为0则表示UART接收到的字符非空,将接收到的字符读入shell的缓冲区,使用Offset表示写入字符在缓冲区中的偏移(用于定位),当偏移超出shell缓冲区的最大长度时,将其重置为0,从而实现循环缓冲区的效果,最后调用PRT_SemPost函数,发送信号量sem_uart_rx,通知其他可能在等待UART接收数据的任务已经读入新的字符。

4.在src/bsp目录下的prt_exc.c文件中修改中断激活函数:

在这里插入图片描述

当接收到的中断处理号为33时,调用接受处理函数

5.在src/kernel/task目录下的prt_task.c文件中加入display函数

在这里插入图片描述

这个函数主要是用于后续Shell的top指令对应的实际操作函数,依次遍历g_runQueue队列,按照优先级打印出所有任务。

6.在src/kernel/tick目录下的prt_tick.c文件中加入display函数

在这里插入图片描述

用于后续Shell的tick指令的实际操作,打印出当前已经进行的时钟中断次数。

7.在src/shell目录下新建shmsg.c文件

OS_SEC_TEXT void ShellTask(uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4)
{
    U32 ret;
    char ch;
    char cmd[SHELL_SHOW_MAX_LEN];
    U32 idx;
    ShellCB *shellCB = (ShellCB *)param1;

    while (1) {
        PRT_Printf("\nminiEuler # ");
        idx = 0;
        for(int i = 0; i < SHELL_SHOW_MAX_LEN; i++)
        {
            cmd[i] = 0;
        }

        while (1){
            PRT_SemPend(sem_uart_rx, OS_WAIT_FOREVER);

            // 读取shellCB缓冲区的字符
            ch = shellCB->shellBuf[shellCB->shellBufReadOffset];
            cmd[idx] = ch;
            idx++;
            shellCB->shellBufReadOffset++;
            if(shellCB->shellBufReadOffset == SHELL_SHOW_MAX_LEN)
                shellCB->shellBufReadOffset = 0;

            PRT_Printf("%c", ch); //回显
            if (ch == '\r'){
                // PRT_Printf("\n");
                if(cmd[0]=='t' && cmd[1]=='o' && cmd[2]=='p'){
                    OsDisplayTasksInfo();
                } else if(cmd[0]=='t' && cmd[1]=='i' && cmd[2]=='c' && cmd[3]=='k'){
                    OsDisplayCurTick();
                }
                break;
            }

        }
    }
}

这段代码的功能很简单,首先输出Shell命令行的提示符“minieuler #”,然后根据Shell缓冲区内的字符(即为输入的指令)进行相应的操作,本实验已经实现的有top指令和tick指令,功能实现在前文中已经详细解释,top指令按照优先级打印出队列中的所有任务,tick指令打印出当前已经执行的时钟中断数,新增加的指令会在后文的作业中详细阐述。

OS_SEC_TEXT U32 ShellTaskInit(ShellCB *shellCB)

{

    U32 ret = 0;

    struct TskInitParam param = {0};

    _// task 1_

    _// param.stackAddr = 0;_

    param.taskEntry = (TskEntryFunc)ShellTask;

    param.taskPrio = 9;

    _// param.name = "Test1Task";_

    param.stackSize = 0x1000; _//__固定4096,参见prt_task_init.c的OsMemAllocAlign_

    param.args[0] = (uintptr_t)shellCB;

    TskHandle tskHandle1;

    ret = PRT_TaskCreate(&tskHandle1, &param);

    if (ret) {

        return ret;

    }

    ret = PRT_TaskResume(tskHandle1);

    if (ret) {

        return ret;

    }

}

这个函数主要目的是使用给定的参数初始化并启动一个新的ShellTask任务。

至此,Shell的底层初始化已经全部完成。

三、 测试及分析

在这里插入图片描述

能够正常运行本实验自带的两条Shell指令

四、 Lab9作业

在实现完Shell的底层原理之后,我们还需要在main函数中启动Shell程序:

在这里插入图片描述

引用外部文件中定义的一系列初始化文件,同时定义本实验中的shellCB控制块

在这里插入图片描述

然后调用初始化函数对Shell进行初始化,就可以顺利启动Shell程序了

这里实现了三条额外的指令:第一条是Shell程序中不可或缺的help指令,可以打印出当前所有的可用指令以及指令用途:

在这里插入图片描述

第二条是清屏操作Clear:

在这里插入图片描述

第三条是退出操作exit:

在这里插入图片描述

演示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

五、心得体会

通过这个实验,我更深入地理解了命令行Shell的工作原理和底层实现,也顺利实现自己写的两条指令;至此,操作系统课程的所有实验落下帷幕,我本人是感慨万分的,从最开始的什么都看不懂、到处找资料、实验代码一看一整天、实验环境一配一整天,到顺利完成所有的实验,实现了一个自己的简单操作系统内核:MiniEuler,还是成就感满满的。很感谢有这个机会能接触到这么底层的实验,让原本遥不可及的操作系统变得咫尺可得,我也同样明白这只是前行的一小步,未来的学习道阻且长。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1918533.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Splashtop 在医疗与制药领域的业务增长近五倍

2024年7月10日 加利福尼亚州库比蒂诺 Splashtop 是安全远程访问和 IT 支持解决方案领域的领先企业&#xff0c;该公司今天宣布&#xff0c;在医疗与制药领域业务同比增长492%&#xff0c;取得了里程碑式的成就。快速发展的数字实验室环境和持续的网络安全威胁需要实施无缝、安…

AWS无服务器 应用程序开发—第十七章 Application Composer

Application Composer 是 AWS 提供的一种可视化工具&#xff0c;用于设计和构建无服务器应用程序。它通过拖放界面简化了无服务器架构的创建过程&#xff0c;使开发者能够更直观地设计和配置应用程序的各个组件。 主要功能 可视化设计 通过拖放界面&#xff0c;开发者可以轻…

科技与水利的完美融合:从数据采集到智能决策,全面解析智慧水利解决方案如何助力水利行业实现智能化管理

本文关键词&#xff1a;智慧水利、智慧水利工程、智慧水利发展前景、智慧水利技术、智慧水利信息化系统、智慧水利解决方案、数字水利和智慧水利、数字水利工程、数字水利建设、数字水利概念、人水和协、智慧水库、智慧水库管理平台、智慧水库建设方案、智慧水库解决方案、智慧…

如何搭建互联网医院系统源码?医疗陪诊APP开发实战详解

今天&#xff0c;小编将为大家讲解如何搭建一个完整的互联网医院系统源码&#xff0c;并介绍医疗陪诊APP的开发实战。 一、互联网医院系统的架构设计 搭建一个完整的互联网医院系统&#xff0c;需要从架构设计开始。一个典型的互联网医院系统通常包含以下几个核心模块&#xf…

钡铼ARMxy控制器在智能网关中的应用

随着IoT物联网技术的飞速发展&#xff0c;智能网关作为连接感知层与网络层的枢纽&#xff0c;可以实现感知网络和通信网络以及不同类型感知网络之间的协议转换。钡铼技术的ARMxy系列控制器凭借其高性能、低功耗和高度灵活性的特点&#xff0c;在智能网关中发挥了关键作用&#…

KEIL5 MDK的(官网)下载安装(Win11)

一、KEIL5 MDK下载 1、Keil官网下载&#xff1a;Keil Product Downloadshttps://www.keil.com/download/product/ 支持包和破解软件和V5编译器下载链接 链接&#xff1a;https://pan.baidu.com/s/1ery0Q3FAR8_bLLlPQHSFNg?pwd9pxf 提取码&#xff1a;9pxf 选择最新版本下载&…

【leetcode】滑动窗口专题

文章目录 1.长度最小的子数组2.无重复字符的最长子串3.最大连续1的个数III4.将x减小到0的最小操作数5.水果成篮6.找到字符串中所有字母异位词7.串联所有单词的子串8.最小覆盖子串 1.长度最小的子数组 leetcode 209.长度最小的子数组 看到这个题目&#xff0c;第一眼肯定想到的…

从人工巡检到智能预警:视频AI智能监控技术在水库/河湖/水利防汛抗洪中的应用

一、背景需求分析 近日&#xff0c;我国多省市遭遇连日暴雨&#xff0c;导致水库、湖泊、河道等水域水位暴涨&#xff0c;城市内涝频发。随着夏季汛期的到来&#xff0c;降雨天气频繁&#xff0c;水利安全管理面临严峻挑战。为保障水库安全、预防和减少洪涝灾害&#xff0c;采…

神经网络识别数字图像案例

学习资料&#xff1a;从零设计并训练一个神经网络&#xff0c;你就能真正理解它了_哔哩哔哩_bilibili 这个视频讲得相当清楚。本文是学习笔记&#xff0c;不是原创&#xff0c;图都是从视频上截图的。 1. 神经网络 2. 案例说明 具体来说&#xff0c;设计一个三层的神经网络。…

Qt常用基础控件总结—带边框的部件(QFrame和QLabel)

带边框的部件 框架控件QFrame类 QFrame类介绍 QFrame 类是带有边框的部件的基类,带边框部件的特点是有一个明显的边框,QFrame类就是用来实现边框的不同效果的(把这种效果称为边框样式),所有继承自 QFrame 的子类都可以使用 QFrame 类实现的效果。 部件通常是矩形的(其他…

图纸文档管理新篇章:陕西航沣与三品软件合作 优化研发流程

近日&#xff0c;陕西航沣新材料有限公司与三品软件正式达成合作协议&#xff0c;共同打造高效、智能的图纸文档管理平台。此次合作旨在赋能陕西航沣在高性能碳纤维增强纸基摩擦材料领域的创新与发展&#xff0c;提升企业的核心竞争力。 客户简介 陕西航沣新材料有限公司&…

脚本批量修改文件名 格式xx.bat

批量修改文件名适用于windows系统 分为4步 1.新建一个 批量修改文件名.txt文件 2.复制下面代码&#xff0c;保存 echo off chcp 65001 >nul set a0 setlocal EnableDelayedExpansion for %%n in (*.png) do (set /A a1ren "%%n" "影魅!a!.jpg" )3.修…

C语言-顺序表

&#x1f3af;引言 欢迎来到HanLop博客的C语言数据结构初阶系列。在这个系列中&#xff0c;我们将深入探讨各种基本的数据结构和算法&#xff0c;帮助您打下坚实的编程基础。本次我将为你讲解。顺序表&#xff08;也称为数组&#xff09;是一种线性表&#xff0c;因其简单易用…

Base64文件流查看下载PDF方法-CSDN

问题描述 数票通等接口返回的PDF类型发票是以Base64文件流的方式返回的&#xff0c;无法直接查看预览PDF发票&#xff0c; 处理方法 使用第三方在线工具&#xff1a;https://www.jyshare.com/front-end/61/ 在Html代码框中粘贴如下代码 <embed type"application/pd…

LeetCode LCR024.反转链表 经典题目 C写法

LeetCode LCR024.反转链表 经典题目C写法 第一种思路&#x1f9d0;&#xff1a; ​ 使用三个指针&#xff0c;n1,n2,n3&#xff0c;n1为空&#xff0c;n2为头结点&#xff0c;n3为头结点的next。开始反转后&#xff0c;n1赋值给n2的next&#xff0c;n2赋值给n1&#xff0c;n3赋…

VBA 批量发送邮件

1. 布局 2. 代码 前期绑定的话&#xff0c;需要勾选 Microsoft Outlook 16.0 Object Library Option ExplicitConst SEND_Y As String "Yes" Const SEND_N As String "No" Const SEND_SELECT_ALL As String "Select All" Const SEND_CANCEL…

ASP.NET Web应用中的 Razor Pages/MVC/Web API/Blazor

如果希望使用ASP.NET Core创建新的 Web 应用程序&#xff0c;应该选择哪种方法&#xff1f;Razor Pages还是 MVC&#xff08;模型-视图-控制器&#xff09;&#xff0c;又或者使用Web API Vue/React/......。 每种方法都有各自的优点和缺点。 什么是 MVC&#xff1f; 大多数服…

Windows桌面上透明的记事本怎么设置

作为一名经常需要记录灵感的作家&#xff0c;我的Windows桌面总是布满了各种文件和窗口。在这样的环境下&#xff0c;一个传统的记事本应用往往会显得突兀&#xff0c;遮挡住我急需查看的资料。于是&#xff0c;我开始寻找一种既能满足记录需求&#xff0c;又能保持桌面整洁美观…

ozon商家版本APP下载,ozon商家版本是怎么样的

在数字化时代&#xff0c;电子商务平台正以前所未有的速度扩张其市场份额&#xff0c;其中俄罗斯的Ozon平台便是典型代表。作为Ozon平台的商家&#xff0c;了解和掌握Ozon商家版本APP的使用对于提升经营效率、把握销售机会至关重要。本篇文章将为您解析Ozon商家版本APP的下载途…

搭建邮局服务器的配置步骤?如何管理协议?

搭建邮局服务器需要考虑的安全措施&#xff1f;怎么搭建服务器&#xff1f; 在现代互联网环境中&#xff0c;电子邮件是重要的沟通工具。为了保证信息传递的稳定性和安全性&#xff0c;许多企业选择自行搭建邮局服务器。AokSend将详细介绍搭建邮局服务器的配置步骤&#xff0c…