NR_shell运行流程简析
nr_shell 是一套开源 shell 框架,基于框架可创建终端交互功能。
为了记录终端输入指令,以及进行解析处理,nr_shell 提供了一套 cmd 结构体,具体如下:
typedef struct static_cmd_function_struct
{char cmd[NR_SHELL_CMD_NAME_MAX_LENGTH];void (*fp)(char argc, char *argv);char *description;
} static_cmd_st;typedef struct shell_history_queue_struct
{unsigned short int fp;unsigned short int rp;unsigned short int len;unsigned short int index;unsigned short int store_front;unsigned short int store_rear;unsigned short int store_num;char queue[NR_SHELL_MAX_CMD_HISTORY_NUM + 1];char buf[NR_SHELL_CMD_HISTORY_BUF_LENGTH + 1];
} shell_his_queue_t;typedef struct nr_shell
{char user_name[NR_SHELL_USER_NAME_MAX_LENGTH];const static_cmd_st *static_cmd;shell_his_queue_st cmd_his;
} shell_st;
nr_shell 启动后,shell_st 结构体将作为 nr_shell 的实例对象维护 nr_shell 的运行环境。
根据结构体可知 shell_st 结构将记录当前用户的名称,当前运行的指令,以及运行过的历史指令。当输入指令格式后,将通过 shell 函数进行解析处理。
对于指令的具体解析,nr_shell 提供了 ansi_st 进行处理。关于 ansi_st 结构体的作用如下:
ansi_st nr_ansi;typedef struct nr_ansi_struct
{short p;unsigned int counter;char current_line[NR_ANSI_LINE_SIZE];char combine_buf[NR_ANSI_CTRL_MAX_LEN];char cmd_num;char combine_state;
} ansi_st;//初始阶段,counter 代表指令格式字符串计数为0,p 代表当前字符索引为 -1,current_line 代表指令格式字符串
void ansi_init(ansi_st *ansi)
{ansi->counter = 0; ansi->p = -1;ansi->current_line[ansi->counter] = '\0';ansi->cmd_num = 0;ansi->combine_state = ANSI_NO_CTRL_CHAR;
}
接下来是完整的字符串解析过程:
对输入的字符串逐字解析,首先判断其是否为特殊符号,比如:'\b','\n','\033' 等,若不是则进行通用处理,否则参考对应的处理办法处理。
#define shell(c) \{ \if (ansi_get_char(c, &nr_ansi) == NR_SHELL_END_CHAR) \{ \shell_parser(&nr_shell, nr_ansi.current_line); \ansi_clear_current_line(&nr_ansi); \} \}char ansi_get_char(char x, ansi_st *ansi)
{int cmd_id = -1;if (ansi->combine_state == ANSI_NO_CTRL_CHAR) {cmd_id = ansi_search_char(x, nr_ansi_in_special_symbol);if (cmd_id >= 0){if (nr_ansi_in_special_symbol_fun[cmd_id] != NULL){nr_ansi_in_special_symbol_fun[cmd_id](ansi);}}else if (x == '\033'){ansi->combine_state = ANSI_WAIT_CTRL_CHAR_END;ansi->combine_buf[ansi->cmd_num] = x;ansi->cmd_num++;}else{nr_ansi_common_char_slover(ansi, x);}}else if (ansi->combine_state == ANSI_WAIT_CTRL_CHAR_END){ansi->combine_buf[ansi->cmd_num] = x;if (('a' <= x && 'z' >= x) || ('A' <= x && 'Z' >= x) || x == '~'){cmd_id = ansi_search_char(x, nr_ansi_in_cmd);nr_ansi_in_cmd_fun[cmd_id](ansi);ansi->cmd_num = 0;anis->combine_state = ANSI_NO_CTRL_CHAR;}else if (ansi->cmd_num > 18){ansi->cmd_num = 0;ansi->combine_state = ANSI_NO_CTRL_CHAR;}else{ansi->cmd_num++;}}else {ansi->combine_state = ANSI_NO_CTRL_CHAR;}return x;
}int ansi_search_char(char x, const char *buf)
{int i = 0;for (i = 0; (buf[i] != x) && (buf[i] != '\0'); i++);if (buf[i] != '\0') {return i;}else {return -1;}
}void nr_ansi_common_char_slover(ansi_st *ansi, char x)
{unsigned int i;if (ansi->counter < NR_ANSI_LINE_SIZE - 2){//该判断条件的目的是将 '\0' 字符向后复制,空出中间字符添加新的字符if (ansi->p < ansi->counter) {for (i = ansi->counter; i > ansi->p; i--){ansi->current_line[i] = ansi->current_line[i - 1];}}//当前字符位置与字符串个数自增ansi->p++;ansi->counter++;//添加输入的字符ansi->current_line[ansi->p] = x;//字符串添加结束标志符ansi->current_line[ansi->counter] = '\0'if (ansi->p + 1 < ansi->counter) {shell_printf("\033[1@");}#ifndef NR_MICRO_SHELL_SIMULATORansi_show_char(x);
#endif} else{ansi->counter = NR_ANSI_LINE_SIZE - 3;if (ansi->p >= ansi->counter){ansi->p = ansi->counter - 1;}ansi->current_line[ansi->counter] = '\0';}
}void shell_parser(shell_st *shell, char *str)
{char argc = 0;char argv[NR_SHELL_CMD_LINE_MAX_LENGTH + NR_SHELL_CMD_PARAS_MAX_NUM];char *token = str;shell_fun_t fp;char index = NR_SHELL_CMD_PARAS_MAX_NUM;if (shell_his_queue_search_cmd(&shell->cmd_his, str) == 0 && str[0] != '\0'){shell_his_queue_add_cmd(&shell->cmd_his, str);}if (strlen(str) > NR_SHELL_CMD_LINE_MAX_LENGTH){shell_printf("this command is too long."NR_SHELL_NEXT_LINE);shell_printf("%s", shell->user_name);return;}token = nr_shell_strtok(token, " ");//从指令表中查看当前指令是否存在,因此需根据实际情况在指令表中添加fp = shell_search_cmd(shell, str);if (fp == NULL){if (isalpha(str[0])){shell_printf("no command named: %s"NR_SHELL_NEXT_LINE, token);}}else{argv[argc] = index;strcpy(argv + index, str);index += strlen(str) + 1;argc++;token = nr_shell_strtok(NULL, " ");//循环获取指令参数while (token != NULL){argv[argc] = index;strcpy(argv + index, token);index += strlen(token) + 1;argc++;token = nr_shell_strtok(NULL, " ");}}if (fp != NULL){fp(argc, argv); //执行指令对应的函数接口}
}
关于 nr_shell 对指令的支持,主要通过框架中的全局变量 nr_shell 完成。
新指令目前不支持接口添加,只能直接在数组表中直接添加。
shell_st nr_shell = {
{.user_name = NR_SHELL_USER_NAME,.static_cmd = nr_cmd_start_add;
};#define nr_cmd_start_add (&static_cmd[0])const static_cmd_st static_cmd[] =
{{"ls", shell_ls_cmd},{"test", shell_test_cmd},{"\0", NULL}
};
以上,就是对 nr_shell 框架的简单分析,只针对 nr_shell 的运作流程,以及新指令的添加。注:特殊指令,比如:方向键等未做分析。
相关文章:
NR_shell运行流程简析
nr_shell 是一套开源 shell 框架,基于框架可创建终端交互功能。 为了记录终端输入指令,以及进行解析处理,nr_shell 提供了一套 cmd 结构体,具体如下:typedef struct static_cmd_function_struct {char cmd[NR_SHELL_CM…...
CSS Fonts(字体)
CSS Fonts(字体) 在网页设计中,字体是传达信息情感和风格的关键元素。CSS(层叠样式表)提供了丰富的字体样式和属性,使得网页设计者能够根据需求选择合适的字体,从而提升用户体验。本文将详细介绍CSS字体相关的知识,包括字体的选择、加载、样式设置等。 字体的选择 选…...
基于Django的Boss直聘IT岗位可视化分析系统的设计与实现
【Django】基于Django的Boss直聘IT岗位可视化分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python作为主要开发语言,利用Django这一高效、安全的W…...
linux系统中的 scp的使用方法
SCP(Secure Copy Protocol)是一种通过加密的方式在本地主机和远程主机之间安全地传输文件的协议。 它是基于SSH协议的扩展,允许用户在不同主机之间进行文件复制和传输,是Linux和Unix系统中常用的工具之一。 在嵌入式Linux软件的…...
x5music3.0 admin_index.php 后台权限绕过漏洞复现(附脚本)
免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 0x0…...
【单链表算法实战】解锁数据结构核心谜题——相交链表
题目如下: 解题过程如下: 相交链表只可以在中间任意位置/头/尾结点相交,如下图: 一个next指针只能指向一块地址,所以不会出现这种情况: 在返回相交链表的起始结点之前先要判断两个链表是否相交࿰…...
Crewai框架添加日志功能
一开始看官方文档以为要用callback这个注释在一个自定义函数上输出日志,结果弄半天都没有结果,最后发已经有现成的方法了(一开始搜log都没搜到这个方法) 只要添加这个output_log_file配置参数即可,由于我的项目只有一…...
【2025年数学建模美赛E题】(农业生态系统)完整解析+模型代码+论文
生态共生与数值模拟:生态系统模型的物种种群动态研究 摘要1Introduction1.1Problem Background1.2Restatement of the Problem1.3Our Work 2 Assumptions and Justifications3 Notations4 模型的建立与求解4.1 农业生态系统模型的建立与求解4.1.1 模型建立4.1.2求解…...
Linux(Centos、Ubuntu) 系统安装jenkins服务
该文章手把手演示在Linux系统下如何安装jenkins服务、并自定义jenkins数据文件位置、以及jenkins如何设置国内镜像源加速,解决插件下载失败问题 安装方式:war包安装 阿里云提供的war下载源地址:https://mirrors.aliyun.com/jenkins/war/?s…...
2013年蓝桥杯第四届CC++大学B组真题及代码
目录 1A:高斯日记(日期计算) 2B:马虎的算式(暴力模拟) 3C:第39级台阶(dfs或dp) 4D:黄金连分数(递推大数运算) 5E:前缀…...
TDengine 做为 FLINK 数据源技术参考手册
Apache Flink 是一款由 Apache 软件基金会支持的开源分布式流批一体化处理框架,可用于流处理、批处理、复杂事件处理、实时数据仓库构建及为机器学习提供实时数据支持等诸多大数据处理场景。与此同时,Flink 拥有丰富的连接器与各类工具,可对接…...
21.2、网络设备安全机制与实现技术
目录 网络设备安全机制与实现技术 - 认证技术网络设备安全机制与实现技术 - 访问控制网络设备安全机制与实现技术 - 信息加密网络设备安全机制与实现技术 - 安全通信网络设备安全机制与实现技术 - 日志审计网络设备安全机制与实现技术 - 安全增强网络设备安全机制与实现技术 - …...
数据结构:二叉树—面试题(二)
1、二叉树的最近公共祖先 习题链接https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/description/ 描述: 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点…...
OFD、PDF 电子签章系统处理流程
在C#中实现电子签章系统的处理流程,可以参考以下步骤和技术实现: 1. 电子签章系统的基本流程 电子签章系统的核心流程包括以下几个步骤: 密钥生成:生成公钥和私钥对,私钥由签章人保管,公钥用于验证签名。…...
分布式微服务系统简述
distributed microservice 分布式与微服务的定义及关系;分布式微服务架构里的各组件,如:配置中心、服务注册/发现、服务网关、负载均衡器、限流降级、断路器、服务调用、分布式事务等;spring cloud 介绍及实现案例,如…...
【Linux】列出所有连接的 WiFi 网络的密码
【Linux】列出所有连接的 WiFi 网络的密码 终端输入 sudo grep psk /etc/NetworkManager/system-connections/*会列出所有连接过 Wifi 的信息,格式类似 /etc/NetworkManager/system-connections/AAAAA.nmconnection:pskBBBBBAAAAA 是 SSID,BBBBB 是对…...
电脑无法开机,重装系统后没有驱动且驱动安装失败
电脑无法开机,重装系统后没有驱动且驱动安装失败 前几天电脑突然坏了,电脑卡住后,强制关机,再开机后开机马上就关机。尝试无数次开机后失败,进入BIOS界面,发现已经没有Windows系统了。重新安装系统后&…...
基于SpringBoot格式化实体的时间类型以及静态注入依赖
一. 场景描述 在进行前后端交互时,发现实体的LocalDateTime返回的格式是这样的: 这不符合我们日常习惯的格式 “年-月-日 时:分:秒”,于是上网学习了前辈 励碼的文章SSM项目中LocalDateTime格式化最佳实践_localdatetime 格式化-CSDN博客解决…...
技术总结:FPGA基于GTX+RIFFA架构实现多功能SDI视频转PCIE采集卡设计方案
目录 1、前言工程概述免责声明 3、详细设计方案设计框图SDI 输入设备Gv8601a 均衡器GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGBFDMA图像缓存RIFFA用户数据控制RIFFA架构详解Xilinx 7 Series Integrated Block for PCI ExpressRIFFA驱动及其安装QT上位机HDMI输出RGB转BT…...
Flink读写Kafka(Table API)
前面(Flink读写Kafka(DataStream API)_flink kafka scram-CSDN博客)我们已经讲解了使用DataStream API来读取Kafka,在这里继续讲解下使用Table API来读取Kafka,和前面一样也是引入相同的依赖即可。 <dependency> <groupId>org.apache.flink</groupId&…...
迷宫问题求解:从递归到队列的算法实战与性能对比
1. 迷宫问题与三种经典解法 迷宫问题就像我们小时候玩的走迷宫游戏,需要在错综复杂的路径中找到一条从起点到终点的通路。在计算机科学中,迷宫被抽象成一个二维矩阵,其中0代表可通行的路径,1代表障碍物。这个问题看似简单…...
Kazumi WebDAV同步功能详解:实现跨设备番剧数据互通的无缝体验
Kazumi WebDAV同步功能详解:实现跨设备番剧数据互通的无缝体验 【免费下载链接】Kazumi 基于自定义规则的番剧采集APP,支持流媒体在线观看,支持弹幕,支持实时超分辨率。 项目地址: https://gitcode.com/gh_mirrors/ka/Kazumi …...
OpenAirInterface (OAI) 实战:如何用USRP搭建你的第一个5G仿真环境(附避坑指南)
OpenAirInterface (OAI) 实战:如何用USRP搭建你的第一个5G仿真环境(附避坑指南) 当5G技术从实验室走向商业化时,开源软件无线电平台OpenAirInterface(OAI)正成为开发者验证创新想法的关键工具。不同于商业设…...
YOLOv8预测结果一键导出:自定义路径+日期文件夹,还能合并所有标签到单个TXT文件
YOLOv8预测结果高效管理:自动化归档与标签合并实战指南 当你在使用YOLOv8完成目标检测任务后,是否经常遇到这样的困扰:检测结果散落在不同文件夹中难以追溯,标签文件分散在各个角落不便统计,每次手动整理既耗时又容易出…...
白鲸开源架构师获邀成为 ASF Member
在技术领域,我们常常被那些闪耀的、可见的成果所吸引。今天,这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力,让我们得以一窥未来的轮廓。然而,作为在企业一线构建、部署和维护复杂系统的实践者,我们深知…...
OFA视觉问答模型惊艳效果:复杂背景中主物体识别与属性描述能力
OFA视觉问答模型惊艳效果:复杂背景中主物体识别与属性描述能力 1. 模型效果惊艳展示 OFA视觉问答模型在复杂场景中的表现令人印象深刻。这个模型能够准确识别图片中的主要物体,并详细描述其属性特征,就像有一个专业的图像分析师在为你解读图…...
cv_resnet101_face-detection_cvpr22papermogface 模型部署的网络安全考量:防范403 Forbidden等常见攻击
cv_resnet101_face-detection_cvpr22papermogface 模型部署的网络安全考量:防范403 Forbidden等常见攻击 把一个人脸检测模型,比如 cv_resnet101_face-detection_cvpr22papermogface,部署成一个Web API,这事儿听起来挺酷的。想象…...
从LED灯变化理解计算机移位运算:手把手教你用实验箱验证带进位左移
从LED灯变化理解计算机移位运算:手把手教你用实验箱验证带进位左移 在计算机组成原理的学习中,移位运算是一个看似简单却蕴含深度的概念。当我们面对抽象的二进制数字在寄存器中"移动"时,往往难以形成直观理解。而通过实验箱上的L…...
开源工具优化Cursor API调用:突破限制提升开发效率的完整方案
开源工具优化Cursor API调用:突破限制提升开发效率的完整方案 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached y…...
04. Web可访问性最佳实践:让每个用户都能平等访问
04. Web可访问性最佳实践:让每个用户都能平等访问 引言 Web 可访问性是前端开发的重要组成部分,它确保所有用户,包括残障人士,都能平等地访问和使用网站。作为一名把代码当散文写的 UI 匠人,我始终认为:好…...
