shell编辑,解析,执行三步走过程解析

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    博客输出站点(国内):http://weharmonyos.com
    博客输出站点(国外):https://openharmony.github.io
    注解文件系统:https://gitee.com/weharmony/third_party_NuttX
    注解协议栈:https://gitee.com/weharmony/third_party_lwip
    注解编译子系统:https://gitee.com/weharmony/build_lite
上级 baa667d6
......@@ -45,11 +45,11 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
//一个shell命令的结构体,命令有长有短,鸿蒙采用了可变数组的方式实现
typedef struct {
unsigned int count;
SH_List list;
char cmdString[0];
unsigned int count; //字符数量
SH_List list; //双向链表
char cmdString[0]; //字符串,可变数组的一种实现方式.
} CmdKeyLink;
#define NEED_NEW_LINE(timesPrint, lineCap) ((timesPrint) % (lineCap) == 0)
......
......@@ -44,11 +44,11 @@ extern "C" {
/*
* Description: the info struct after cmd parser
*/
typedef struct {
unsigned int paramCnt; /* count of para */
CmdType cmdType; /* cmd type, judge cmd keyword */
char cmdKeyword[CMD_KEY_LEN]; /* cmd keyword str */
char *paramArray[CMD_MAX_PARAS];
typedef struct {//命令解析器
unsigned int paramCnt; /* count of para *///参数数量
CmdType cmdType; /* cmd type, judge cmd keyword *///命令类型
char cmdKeyword[CMD_KEY_LEN]; /* cmd keyword str *///关键字,最多16个字符
char *paramArray[CMD_MAX_PARAS];//参数内容,最多32个参数
} CmdParsed;
extern unsigned int OsCmdParse(char *cmdStr, CmdParsed *cmdParsed);
......
......@@ -51,7 +51,7 @@ extern "C" {
#define CMD_KEY_LEN 16U
#define CMD_MAX_LEN (256U + CMD_KEY_LEN)
#define CMD_KEY_NUM 32
#define CMD_HISTORY_LEN 10
#define CMD_HISTORY_LEN 10 //最多保存十个命令行记录
#define CMD_MAX_PATH 256
#define DEFAULT_SCREEN_WIDTH 80
#define DEFAULT_SCREEN_HEIGNT 24
......@@ -70,34 +70,34 @@ extern "C" {
typedef size_t bool;
typedef struct {
unsigned int consoleID;
pthread_t shellTaskHandle;
pthread_t shellEntryHandle;
void *cmdKeyLink;
void *cmdHistoryKeyLink;
void *cmdMaskKeyLink;
unsigned int shellBufOffset;
unsigned int shellKeyType;
sem_t shellSem;
pthread_mutex_t keyMutex;
pthread_mutex_t historyMutex;
char shellBuf[SHOW_MAX_LEN];
char shellWorkingDirectory[PATH_MAX];
unsigned int consoleID; //控制台ID
pthread_t shellTaskHandle; //shell服务端任务
pthread_t shellEntryHandle;//shell客户端任务
void *cmdKeyLink; //命令链表,所有敲过的命令链表
void *cmdHistoryKeyLink; //命令的历史记录链表,去重,10个
void *cmdMaskKeyLink; //主要用于方向键上下遍历历史命令
unsigned int shellBufOffset; //buf偏移量
unsigned int shellKeyType; //按键类型
sem_t shellSem; //shell信号量
pthread_mutex_t keyMutex; //操作cmdKeyLink的互斥量
pthread_mutex_t historyMutex; //操作cmdHistoryKeyLink的互斥量
char shellBuf[SHOW_MAX_LEN]; //接受shell命令 buf大小
char shellWorkingDirectory[PATH_MAX];//shell工作目录
} ShellCB;
/* All support cmd types */
typedef enum {
CMD_TYPE_SHOW = 0,
CMD_TYPE_STD = 1,
CMD_TYPE_EX = 2,
CMD_TYPE_BUTT
typedef enum {//所有支持的类型
CMD_TYPE_SHOW = 0, //用户怎么输入就怎么显示出现,包括 \n \0 这些字符也都会存在
CMD_TYPE_STD = 1, //支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。
CMD_TYPE_EX = 2, //不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。
CMD_TYPE_BUTT
} CmdType;
typedef enum {
CMD_KEY_UP = 0,
CMD_KEY_DOWN = 1,
CMD_KEY_RIGHT = 2,
CMD_KEY_LEFT = 4,
CMD_KEY_UP = 0, //方向上键
CMD_KEY_DOWN = 1, //方向下键
CMD_KEY_RIGHT = 2, //方向左键
CMD_KEY_LEFT = 4, //方向右键
CMD_KEY_BUTT
} CmdKeyDirection;
......
......@@ -37,8 +37,8 @@
#include "unistd.h"
#include <sys/syscall.h>
ShellCB *g_shellCB = NULL;
ShellCB *g_shellCB = NULL; //全部shell控制块
//获取shell控制块
ShellCB *OsGetShellCb()
{
return g_shellCB;
......
......@@ -461,7 +461,7 @@ int OsTabCompletion(char *cmdKey, unsigned int *len)
return count;
}
//shell 按键初始化
unsigned int OsShellKeyInit(ShellCB *shellCB)
{
CmdKeyLink *cmdKeyLink = NULL;
......
......@@ -43,7 +43,7 @@
#include "shcmd.h"
//获取命令行
char *GetCmdline(ShellCB *shellCB)
{
CmdKeyLink *cmdkey = shellCB->cmdKeyLink;
......@@ -71,7 +71,7 @@ char *GetCmdline(ShellCB *shellCB)
return cmdNode->cmdString;
}
//保存shell命令历史
static void ShellSaveHistoryCmd(char *string, ShellCB *shellCB)
{
CmdKeyLink *cmdHistory = shellCB->cmdHistoryKeyLink;
......@@ -84,7 +84,7 @@ static void ShellSaveHistoryCmd(char *string, ShellCB *shellCB)
}
(void)pthread_mutex_lock(&shellCB->historyMutex);
if (cmdHistory->count != 0) {
if (cmdHistory->count != 0) {//这个分支的目的是去重,又不遍历整个链表,感觉没多大意义.
cmdNxt = SH_LIST_ENTRY(cmdHistory->list.pstPrev, CmdKeyLink, list);
if (strcmp(string, cmdNxt->cmdString) == 0) {
free((void *)cmdkey);
......@@ -93,22 +93,22 @@ static void ShellSaveHistoryCmd(char *string, ShellCB *shellCB)
}
}
if (cmdHistory->count >= CMD_HISTORY_LEN) {
cmdNxt = SH_LIST_ENTRY(cmdHistory->list.pstNext, CmdKeyLink, list);
SH_ListDelete(&(cmdNxt->list));
SH_ListTailInsert(&(cmdHistory->list), &(cmdkey->list));
free((void *)cmdNxt);
if (cmdHistory->count >= CMD_HISTORY_LEN) {//已经满了的处理,则需要删除一条再插入新的,数量不变,所以不存在 count的 +-
cmdNxt = SH_LIST_ENTRY(cmdHistory->list.pstNext, CmdKeyLink, list);//拿到下一条命令行记录
SH_ListDelete(&(cmdNxt->list));//将自己摘出去
SH_ListTailInsert(&(cmdHistory->list), &(cmdkey->list));//尾部插入新的命令
free((void *)cmdNxt);//释放旧数据
(void)pthread_mutex_unlock(&shellCB->historyMutex);
return;
}
SH_ListTailInsert(&(cmdHistory->list), &(cmdkey->list));
cmdHistory->count++;
SH_ListTailInsert(&(cmdHistory->list), &(cmdkey->list));//从尾部插入
cmdHistory->count++;//历史记录的数量增加
(void)pthread_mutex_unlock(&shellCB->historyMutex);
return;
}
//shell挂起
int ShellPend(ShellCB *shellCB)
{
if (shellCB == NULL) {
......@@ -117,7 +117,7 @@ int ShellPend(ShellCB *shellCB)
return sem_wait(&shellCB->shellSem);
}
//shell通知
int ShellNotify(ShellCB *shellCB)
{
if (shellCB == NULL) {
......@@ -128,11 +128,11 @@ int ShellNotify(ShellCB *shellCB)
}
enum {
STAT_NOMAL_KEY,
STAT_ESC_KEY,
STAT_MULTI_KEY
STAT_NOMAL_KEY, //普通按键
STAT_ESC_KEY, //<ESC>键,支持VT规范
STAT_MULTI_KEY //组合键 例如: <ESC>[30m
};
//检查上下左右键
static int ShellCmdLineCheckUDRL(const char ch, ShellCB *shellCB)
{
int ret = SH_OK;
......@@ -169,7 +169,7 @@ static int ShellCmdLineCheckUDRL(const char ch, ShellCB *shellCB)
}
return SH_NOK;
}
//通知任务解析shell命令
void ShellTaskNotify(ShellCB *shellCB)
{
int ret;
......@@ -178,12 +178,12 @@ void ShellTaskNotify(ShellCB *shellCB)
OsShellCmdPush(shellCB->shellBuf, shellCB->cmdKeyLink);
(void)pthread_mutex_unlock(&shellCB->keyMutex);
ret = ShellNotify(shellCB);
ret = ShellNotify(shellCB);//通知解析shell命令的任务
if (ret != SH_OK) {
printf("command execute failed, \"%s\"", shellCB->shellBuf);
}
}
//解析回车键 , 按回车后的处理
void ParseEnterKey(OutputFunc outputFunc, ShellCB *shellCB)
{
if ((shellCB == NULL) || (outputFunc == NULL)) {
......@@ -204,7 +204,7 @@ NOTIFY:
shellCB->shellBufOffset = 0;
ShellTaskNotify(shellCB);
}
//解析删除键
void ParseDeleteKey(OutputFunc outputFunc, ShellCB *shellCB)
{
if ((shellCB == NULL) || (outputFunc == NULL)) {
......@@ -217,7 +217,7 @@ void ParseDeleteKey(OutputFunc outputFunc, ShellCB *shellCB)
outputFunc("\b \b");
}
}
//解析tab键
void ParseTabKey(OutputFunc outputFunc, ShellCB *shellCB)
{
int ret;
......@@ -233,7 +233,7 @@ void ParseTabKey(OutputFunc outputFunc, ShellCB *shellCB)
}
}
}
//解析普通字符
void ParseNormalChar(char ch, OutputFunc outputFunc, ShellCB *shellCB)
{
if ((shellCB == NULL) || (outputFunc == NULL)) {
......
......@@ -315,12 +315,12 @@ STATIC VOID ConsoleFifoClearup(CONSOLE_CB *console)
console->fifoIn = 0;
(VOID)memset_s(console->fifo, CONSOLE_FIFO_SIZE, 0, CONSOLE_FIFO_SIZE);
}
//控制台buf长度更新
STATIC VOID ConsoleFifoLenUpdate(CONSOLE_CB *console)
{
console->currentLen = console->fifoIn - console->fifoOut;
}
//读取
STATIC INT32 ConsoleReadFifo(CHAR *buffer, CONSOLE_CB *console, size_t bufLen)
{
INT32 ret;
......@@ -339,7 +339,7 @@ STATIC INT32 ConsoleReadFifo(CHAR *buffer, CONSOLE_CB *console, size_t bufLen)
ConsoleFifoLenUpdate(console);
return (INT32)readNum;
}
//
//打开串口或远程登录
INT32 FilepOpen(struct file *filep, const struct file_operations_vfs *fops)
{
INT32 ret;
......@@ -357,7 +357,7 @@ INT32 FilepOpen(struct file *filep, const struct file_operations_vfs *fops)
}
return ret;
}
//向控制台buf中写入结束字符
STATIC INLINE VOID UserEndOfRead(CONSOLE_CB *consoleCB, struct file *filep,
const struct file_operations_vfs *fops)
{
......@@ -376,12 +376,12 @@ enum {
STAT_ESC_KEY, //控制按键,只有 ESC 是
STAT_MULTI_KEY //多个按键,只有 [ 是
};
//用户shell检查上下左右键
STATIC INT32 UserShellCheckUDRL(const CHAR ch, INT32 *lastTokenType)
{
INT32 ret = LOS_OK;
if (ch == 0x1b) { /* 0x1b: ESC */
*lastTokenType = STAT_ESC_KEY;
*lastTokenType = STAT_ESC_KEY;// vt 的控制字符
return ret;
} else if (ch == 0x5b) { /* 0x5b: first Key combination */
if (*lastTokenType == STAT_ESC_KEY) { //遇到 <ESC>[
......@@ -411,7 +411,7 @@ STATIC INT32 UserShellCheckUDRL(const CHAR ch, INT32 *lastTokenType)
}
return LOS_NOK;
}
//是否需要继续
STATIC INT32 IsNeedContinue(CONSOLE_CB *consoleCB, char ch, INT32 *lastTokenType)
{
if (((ch == '\b') && (consoleCB->consoleTermios.c_lflag & ECHO) && (ConsoleFifoEmpty(consoleCB))) ||
......@@ -421,36 +421,36 @@ STATIC INT32 IsNeedContinue(CONSOLE_CB *consoleCB, char ch, INT32 *lastTokenType
return LOS_OK;
}
//输出到终端
STATIC VOID EchoToTerminal(CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops, char ch)
{
if (consoleCB->consoleTermios.c_lflag & ECHO) {
if (ch == '\b') {
(VOID)fops->write(filep, "\b \b", 3);
if (ch == '\b') {//遇到回退字符
(VOID)fops->write(filep, "\b \b", 3);//回退
} else {
(VOID)fops->write(filep, &ch, EACH_CHAR);
(VOID)fops->write(filep, &ch, EACH_CHAR);//向终端写入字符
}
}
}
//存储读取的字符
STATIC VOID StoreReadChar(CONSOLE_CB *consoleCB, char ch, INT32 readcount)
{
{ //读取字符
if ((readcount == EACH_CHAR) && (consoleCB->fifoIn <= (CONSOLE_FIFO_SIZE - 3))) {
if (ch == '\b') {
if (!ConsoleFifoEmpty(consoleCB)) {
consoleCB->fifo[--consoleCB->fifoIn] = '\0';
}
} else {
consoleCB->fifo[consoleCB->fifoIn] = (UINT8)ch;
consoleCB->fifo[consoleCB->fifoIn] = (UINT8)ch;//将字符读入缓冲区
consoleCB->fifoIn++;
}
}
}
//杀死进程组
VOID KillPgrp()
{
INT32 consoleId;
LosProcessCB *process = OsCurrProcessGet();
LosProcessCB *process = OsCurrProcessGet();//获取当前进程
if ((process->consoleID > CONSOLE_NUM -1 ) || (process->consoleID < 0)) {
return;
......@@ -458,9 +458,9 @@ VOID KillPgrp()
consoleId = process->consoleID;
CONSOLE_CB *consoleCB = g_console[consoleId];
(VOID)OsKillLock(consoleCB->pgrpId, SIGINT);
(VOID)OsKillLock(consoleCB->pgrpId, SIGINT);//发送信号 SIGINT对应 键盘中断(ctrl + c)信号
}
//用户使用参数buffer将控制台的buf接走
STATIC INT32 UserFilepRead(CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops,
CHAR *buffer, size_t bufLen)
{
......@@ -482,44 +482,43 @@ STATIC INT32 UserFilepRead(CONSOLE_CB *consoleCB, struct file *filep, const stru
return ret;
}
/* ICANON mode: store data to console buffer, read data and stored data into console fifo */
if (consoleCB->currentLen == 0) {
while (1) {
ret = fops->read(filep, &ch, EACH_CHAR);
if (consoleCB->currentLen == 0) {//如果没有数据
while (1) {//存储数据到控制台buf中
ret = fops->read(filep, &ch, EACH_CHAR);//一个个字符读
if (ret <= 0) {
return ret;
}
if (IsNeedContinue(consoleCB, ch, &lastTokenType))
if (IsNeedContinue(consoleCB, ch, &lastTokenType))//是否继续读
continue;
switch (ch) {
case '\r':
ch = '\n';
ch = '\n';//回车换行
case '\n':
EchoToTerminal(consoleCB, filep, fops, ch);
UserEndOfRead(consoleCB, filep, fops);
ret = ConsoleReadFifo(buffer, consoleCB, bufLen);
needreturn = LOS_OK;
EchoToTerminal(consoleCB, filep, fops, ch);//输出到终端
UserEndOfRead(consoleCB, filep, fops);//给控制台buf加上结束字符
ret = ConsoleReadFifo(buffer, consoleCB, bufLen);//读取控制台buf的信息到参数buffer中
needreturn = LOS_OK;//直接返回
break;
case '\b':
default:
EchoToTerminal(consoleCB, filep, fops, ch);
StoreReadChar(consoleCB, ch, ret);
EchoToTerminal(consoleCB, filep, fops, ch);//输出到终端
StoreReadChar(consoleCB, ch, ret);//将字符保存到控制台的buf中
break;
}
if (needreturn == LOS_OK)
break;
}
} else {
} else {//如果数据准备好了,立即返回
/* if data is already in console fifo, we returen them immediately */
ret = ConsoleReadFifo(buffer, consoleCB, bufLen);
ret = ConsoleReadFifo(buffer, consoleCB, bufLen);//读取控制台buf的信息到参数buffer中
}
return ret;
}
//从控制台读数据
//从串口或远程登录中读数据
INT32 FilepRead(struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen)
{
INT32 ret;
......@@ -537,7 +536,7 @@ INT32 FilepRead(struct file *filep, const struct file_operations_vfs *fops, CHAR
}
return ret;
}
//写数据到串口或远程登录
INT32 FilepWrite(struct file *filep, const struct file_operations_vfs *fops, const CHAR *buffer, size_t bufLen)
{
INT32 ret;
......@@ -551,7 +550,7 @@ INT32 FilepWrite(struct file *filep, const struct file_operations_vfs *fops, con
}
return ret;
}
//关闭串口或远程登录
INT32 FilepClose(struct file *filep, const struct file_operations_vfs *fops)
{
INT32 ret;
......@@ -632,7 +631,7 @@ ERROUT:
set_errno(ret);
return VFS_ERROR;
}
//关闭控制台
STATIC INT32 ConsoleClose(struct file *filep)
{
INT32 ret;
......@@ -677,7 +676,7 @@ STATIC ssize_t DoRead(CONSOLE_CB *consoleCB, CHAR *buffer, size_t bufLen,
return ret;
}
//用户任务从控制台读数据
STATIC ssize_t ConsoleRead(struct file *filep, CHAR *buffer, size_t bufLen)
{
INT32 ret;
......@@ -695,7 +694,7 @@ STATIC ssize_t ConsoleRead(struct file *filep, CHAR *buffer, size_t bufLen)
if (bufLen > CONSOLE_FIFO_SIZE) {
bufLen = CONSOLE_FIFO_SIZE;
}
//检查buffer是否在用户区
userBuf = LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buffer, bufLen);
ret = GetFilepOps(filep, &privFilep, &fileOps);
if (ret != ENOERR) {
......@@ -720,7 +719,7 @@ STATIC ssize_t ConsoleRead(struct file *filep, CHAR *buffer, size_t bufLen)
goto ERROUT;
}
ret = DoRead(consoleCB, sbuffer, bufLen, privFilep, fileOps);
ret = DoRead(consoleCB, sbuffer, bufLen, privFilep, fileOps);//真正的读数据
if (ret < 0) {
goto ERROUT;
}
......@@ -774,12 +773,12 @@ STATIC ssize_t DoWrite(CirBufSendCB *cirBufSendCB, CHAR *buffer, size_t bufLen)
LOS_CirBufUnlock(&cirBufSendCB->cirBufCB, intSave);
/* Log is cached but not printed when a system exception occurs */
if (OsGetSystemStatus() == OS_SYSTEM_NORMAL) {
(VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT);
(VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT);//发送数据事件
}
return writen;
}
//
//用户任务写数据到控制台
STATIC ssize_t ConsoleWrite(struct file *filep, const CHAR *buffer, size_t bufLen)
{
INT32 ret;
......@@ -797,7 +796,7 @@ STATIC ssize_t ConsoleWrite(struct file *filep, const CHAR *buffer, size_t bufLe
if (bufLen > CONSOLE_FIFO_SIZE) {
bufLen = CONSOLE_FIFO_SIZE;
}
//检测buffer是否在用户空间
userBuf = LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buffer, bufLen);
ret = GetFilepOps(filep, &privFilep, &fileOps);
......@@ -822,7 +821,7 @@ STATIC ssize_t ConsoleWrite(struct file *filep, const CHAR *buffer, size_t bufLe
ret = EFAULT;
goto ERROUT;
}
ret = DoWrite(cirBufSendCB, sbuffer, bufLen);
ret = DoWrite(cirBufSendCB, sbuffer, bufLen);//真正的写操作
if (userBuf) {
LOS_MemFree(m_aucSysMem0, sbuffer);
......@@ -1694,7 +1693,7 @@ VOID OsWaitConsoleSendTaskPend(UINT32 taskID)//等待控制台发送任务结束
LosTaskCB *taskCB = NULL;
INT32 waitTime = 3000; /* 3000: 3 seconds */
for (i = 0; i < CONSOLE_NUM; i++) {//循环cpu core
for (i = 0; i < CONSOLE_NUM; i++) {//轮询控制台
console = g_console[i];
if (console == NULL) {
continue;
......
......@@ -66,7 +66,7 @@ typedef struct { //命令节点
/* global info for shell module */
typedef struct {//shell 模块的全局信息
CmdItemNode cmdList;
CmdItemNode cmdList; //命令项节点
UINT32 listNum;//节点数量
UINT32 initMagicFlag;//初始魔法标签 0xABABABAB
LosMux muxLock; //操作链表互斥锁
......@@ -78,7 +78,7 @@ typedef struct {
LOS_DL_LIST list;
CHAR cmdString[0];
} CmdKeyLink;
//shell 静态宏方式注册
#define SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook) \
CmdItem l LOS_HAL_TABLE_ENTRY(shellcmd) = { \
cmdType, \
......
......@@ -60,17 +60,17 @@ extern "C" {
#define XARGS 0xFFFFFFFF /* default args */
#define CMD_MAX_PARAS 32
#define CMD_KEY_LEN 16U
#define CMD_MAX_PARAS 32 //命令参数最大个数
#define CMD_KEY_LEN 16U //关键字长度 例如: 'ls'的长度为2
#define CMD_MAX_LEN (256U + CMD_KEY_LEN)
#define CMD_KEY_NUM 32
#define CMD_HISTORY_LEN 10
#define CMD_MAX_PATH 256
#define DEFAULT_SCREEN_WIDTH 80
#define DEFAULT_SCREEN_HEIGNT 24
#define CMD_KEY_NUM 32 //
#define CMD_HISTORY_LEN 10 //历史记录数量
#define CMD_MAX_PATH 256
#define DEFAULT_SCREEN_WIDTH 80 //屏幕的宽
#define DEFAULT_SCREEN_HEIGNT 24 //屏幕的高
#define SHELL_MODE 0
#define OTHER_MODE 1
#define SHELL_MODE 0 //shell模式
#define OTHER_MODE 1 //其他模式
#define SWITCH_QUOTES_STATUS(qu) do { \
if ((qu) == TRUE) { \
......@@ -85,22 +85,22 @@ extern "C" {
//shell 控制块
typedef struct {
UINT32 consoleID; //控制台ID
UINT32 shellTaskHandle; //处理shell的任务ID
UINT32 shellEntryHandle; //接收shell指令的任务ID
VOID *cmdKeyLink;
VOID *cmdHistoryKeyLink;
VOID *cmdMaskKeyLink;
UINT32 shellTaskHandle; //shell服务端任务
UINT32 shellEntryHandle; //shell客户端任务
VOID *cmdKeyLink; //命令链表,所有敲过的命令链表
VOID *cmdHistoryKeyLink;//命令的历史记录链表,去重,10个
VOID *cmdMaskKeyLink; //主要用于方向键上下遍历历史命令
UINT32 shellBufOffset; //buf偏移量
UINT32 shellKeyType; //键内
UINT32 shellKeyType; //按键类
EVENT_CB_S shellEvent; //事件类型触发
pthread_mutex_t keyMutex;
pthread_mutex_t historyMutex;
pthread_mutex_t keyMutex; //按键互斥量
pthread_mutex_t historyMutex; //历史记录互斥量
CHAR shellBuf[SHOW_MAX_LEN]; //shell命令buf,接受键盘的输入,需要对输入字符解析.
CHAR shellWorkingDirectory[PATH_MAX];//shell的工作目录
} ShellCB;
/* All support cmd types */
typedef enum {//所有支持的按键类型
typedef enum {//所有支持的类型
CMD_TYPE_SHOW = 0, //用户怎么输入就怎么显示出现,包括 \n \0 这些字符也都会存在
CMD_TYPE_STD = 1, //支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。
CMD_TYPE_EX = 2, //不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。
......@@ -119,12 +119,12 @@ typedef enum {//四个方向上下左右键
* Hook for user-defined debug function
* Unify differnt module's func for registration
*/
typedef UINT32 (*CmdCallBackFunc)(UINT32 argc, const CHAR **argv);
typedef UINT32 (*CmdCallBackFunc)(UINT32 argc, const CHAR **argv);//命令回调函数,
/* External interface, need reserved */
typedef CmdCallBackFunc CMD_CBK_FUNC;
typedef CmdType CMD_TYPE_E;
//以动态方式注册命令
extern UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc);
#ifdef __cplusplus
......
......@@ -47,7 +47,7 @@ extern UINT32 ShellTaskInit(ShellCB *shellCB);
extern UINT32 ShellEntryInit(ShellCB *shellCB);
extern VOID ShellCmdLineParse(CHAR c, pf_OUTPUT outputFunc, ShellCB *shellCB);
extern UINT32 ShellMsgTypeGet(CmdParsed *cmdParsed, const CHAR *cmdType);
#define SHELL_CMD_PARSE_EVENT 0x111
#define SHELL_CMD_PARSE_EVENT 0x111 //shell命令解析事件
#ifdef __cplusplus
#if __cplusplus
......
......@@ -41,26 +41,26 @@
#include "los_typedef.h"
#define SHELL_INIT_MAGIC_FLAG 0xABABABAB
#define SHELL_INIT_MAGIC_FLAG 0xABABABAB //shell的魔法数字
#define CTRL_C 0x03 /* 0x03: ctrl+c ASCII */
STATIC CmdModInfo g_cmdInfo;//shell 命令模块信息,上面挂了所有的命令项(ls,cd ,cp ==)
LOS_HAL_TABLE_BEGIN(g_shellcmd, shellcmd);
LOS_HAL_TABLE_END(g_shellcmdEnd, shellcmd);
//获取全局变量
CmdModInfo *OsCmdInfoGet(VOID)
{
return &g_cmdInfo;
}
//释放命令行参数所占内存
STATIC VOID OsFreeCmdPara(CmdParsed *cmdParsed)
{
UINT32 i;
for (i = 0; i < cmdParsed->paramCnt; i++) {
if ((cmdParsed->paramArray[i]) != NULL) {
for (i = 0; i < cmdParsed->paramCnt; i++) {//遍历参数个数
if ((cmdParsed->paramArray[i]) != NULL) {//一个个释放内存
(VOID)LOS_MemFree(m_aucSysMem0, (cmdParsed->paramArray[i]));
cmdParsed->paramArray[i] = NULL;
cmdParsed->paramArray[i] = NULL;//重新初始化
}
}
}
......@@ -499,15 +499,15 @@ LITE_OS_SEC_TEXT_MINOR BOOL OsCmdKeyCheck(const CHAR *cmdKey)
{
const CHAR *temp = cmdKey;
enum Stat {
STAT_NONE,
STAT_DIGIT,
STAT_OTHER
STAT_NONE, //普通
STAT_DIGIT, //数字
STAT_OTHER //其余
} state = STAT_NONE;
if (strlen(cmdKey) >= CMD_KEY_LEN) {
if (strlen(cmdKey) >= CMD_KEY_LEN) {//长度不能超 16个字符
return FALSE;
}
//命令只支持数字,字母,下划线,中划线
while (*temp != '\0') {
if (!((*temp <= '9') && (*temp >= '0')) &&
!((*temp <= 'z') && (*temp >= 'a')) &&
......@@ -515,7 +515,7 @@ LITE_OS_SEC_TEXT_MINOR BOOL OsCmdKeyCheck(const CHAR *cmdKey)
(*temp != '_') && (*temp != '-')) {
return FALSE;
}
//数字
if ((*temp >= '0') && (*temp <= '9')) {
if (state == STAT_NONE) {
state = STAT_DIGIT;
......@@ -591,7 +591,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsCmdAscendingInsert(CmdItemNode *cmd)
LOS_ListTailInsert(&(cmdItem->list), &(cmd->list));
}
//shell 按键初始化
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellKeyInit(ShellCB *shellCB)
{
CmdKeyLink *cmdKeyLink = NULL;
......@@ -661,7 +661,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellSysCmdRegister(VOID)
g_cmdInfo.listNum += index;//命令数量叠加
return LOS_OK;
}
//解析回车或换行键
//将shell命令 string 以 CmdKeyLink 方式加入链表
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdPush(const CHAR *string, CmdKeyLink *cmdKeyLink)
{
CmdKeyLink *cmdNewNode = NULL;
......@@ -671,23 +671,23 @@ LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdPush(const CHAR *string, CmdKeyLink *cmdKe
return;
}
len = strlen(string);
cmdNewNode = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink) + len + 1);
len = strlen(string);//获取string的长度,注意CmdKeyLink结构体中,cmdString[0],可变数组的实现.
cmdNewNode = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink) + len + 1);//申请内核内存
if (cmdNewNode == NULL) {
return;
}
(VOID)memset_s(cmdNewNode, sizeof(CmdKeyLink) + len + 1, 0, sizeof(CmdKeyLink) + len + 1);
if (strncpy_s(cmdNewNode->cmdString, len + 1, string, len)) {
if (strncpy_s(cmdNewNode->cmdString, len + 1, string, len)) {//将string拷贝至cmdString中
(VOID)LOS_MemFree(m_aucSysMem0, cmdNewNode);
return;
}
LOS_ListTailInsert(&(cmdKeyLink->list), &(cmdNewNode->list));
LOS_ListTailInsert(&(cmdKeyLink->list), &(cmdNewNode->list));//从尾部插入链表
return;
}
//显示shell命令历史记录,支持上下键方式
LITE_OS_SEC_TEXT_MINOR VOID OsShellHistoryShow(UINT32 value, ShellCB *shellCB)
{
CmdKeyLink *cmdtmp = NULL;
......@@ -696,19 +696,19 @@ LITE_OS_SEC_TEXT_MINOR VOID OsShellHistoryShow(UINT32 value, ShellCB *shellCB)
errno_t ret;
(VOID)pthread_mutex_lock(&shellCB->historyMutex);
if (value == CMD_KEY_DOWN) {
if (value == CMD_KEY_DOWN) {//方向下键切换下一条历史
if (cmdMask == cmdNode) {
goto END;
}
cmdtmp = LOS_DL_LIST_ENTRY(cmdMask->list.pstNext, CmdKeyLink, list);
cmdtmp = LOS_DL_LIST_ENTRY(cmdMask->list.pstNext, CmdKeyLink, list);//下一条命令
if (cmdtmp != cmdNode) {
cmdMask = cmdtmp;
} else {
goto END;
}
} else if (value == CMD_KEY_UP) {
cmdtmp = LOS_DL_LIST_ENTRY(cmdMask->list.pstPrev, CmdKeyLink, list);
cmdtmp = LOS_DL_LIST_ENTRY(cmdMask->list.pstPrev, CmdKeyLink, list);//上一条命令
if (cmdtmp != cmdNode) {
cmdMask = cmdtmp;
} else {
......@@ -716,18 +716,18 @@ LITE_OS_SEC_TEXT_MINOR VOID OsShellHistoryShow(UINT32 value, ShellCB *shellCB)
}
}
while (shellCB->shellBufOffset--) {
while (shellCB->shellBufOffset--) {//@note_why 这段代码不知道啥意思
PRINTK("\b \b");
}
PRINTK("%s", cmdMask->cmdString);
shellCB->shellBufOffset = strlen(cmdMask->cmdString);
(VOID)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);
ret = memcpy_s(shellCB->shellBuf, SHOW_MAX_LEN, cmdMask->cmdString, shellCB->shellBufOffset);
PRINTK("%s", cmdMask->cmdString);//打印命令
shellCB->shellBufOffset = strlen(cmdMask->cmdString);//获取命令长度
(VOID)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);//整个buf进行重置,
ret = memcpy_s(shellCB->shellBuf, SHOW_MAX_LEN, cmdMask->cmdString, shellCB->shellBufOffset);//将命令拷贝进buf,以便继续添加内容
if (ret != EOK) {
PRINT_ERR("%s, %d memcpy failed!\n", __FUNCTION__, __LINE__);
goto END;
}
shellCB->cmdMaskKeyLink = (VOID *)cmdMask;
shellCB->cmdMaskKeyLink = (VOID *)cmdMask;//记录按上下键命令的位置
END:
(VOID)pthread_mutex_unlock(&shellCB->historyMutex);
......@@ -750,7 +750,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdExec(CmdParsed *cmdParsed, CHAR *cmdStr)
if (ret != LOS_OK) {
goto OUT;
}
//遍历链表
LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(g_cmdInfo.cmdList.list), CmdItemNode, list) {
cmdKey = curCmdItem->cmd->cmdKey;
if ((cmdParsed->cmdType == curCmdItem->cmd->cmdType) &&
......@@ -767,7 +767,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdExec(CmdParsed *cmdParsed, CHAR *cmdStr)
}
OUT:
for (i = 0; i < cmdParsed->paramCnt; i++) {
for (i = 0; i < cmdParsed->paramCnt; i++) {//无效的命令要释放掉保存参数的内存
if (cmdParsed->paramArray[i] != NULL) {
(VOID)LOS_MemFree(m_aucSysMem0, cmdParsed->paramArray[i]);
cmdParsed->paramArray[i] = NULL;
......@@ -816,11 +816,11 @@ STATIC UINT32 OsCmdItemCreate(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNu
return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR;
}
(VOID)memset_s(cmdItemNode, sizeof(CmdItemNode), '\0', sizeof(CmdItemNode));
cmdItemNode->cmd = cmdItem;
cmdItemNode->cmd->cmdHook = cmdProc;
cmdItemNode->cmd->paraNum = paraNum;
cmdItemNode->cmd->cmdType = cmdType;
cmdItemNode->cmd->cmdKey = cmdKey;
cmdItemNode->cmd = cmdItem; //命令项
cmdItemNode->cmd->cmdHook = cmdProc;//回调函数 osShellCmdLs
cmdItemNode->cmd->paraNum = paraNum;//`777`,'/home'
cmdItemNode->cmd->cmdType = cmdType;//关键字类型
cmdItemNode->cmd->cmdKey = cmdKey; //`chmod`
//2.完成构造后挂入全局链表
(VOID)LOS_MuxLock(&g_cmdInfo.muxLock, LOS_WAIT_FOREVER);
OsCmdAscendingInsert(cmdItemNode);//按升序方式插入
......@@ -830,12 +830,12 @@ STATIC UINT32 OsCmdItemCreate(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNu
return LOS_OK;
}
/* open API */ //注册命令至全局
/* open API */ //以动态方式注册命令
LITE_OS_SEC_TEXT_MINOR UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)
{
CmdItemNode *cmdItemNode = NULL;
(VOID)LOS_MuxLock(&g_cmdInfo.muxLock, LOS_WAIT_FOREVER);//1.确保先拿到锁
//1.确保先拿到锁,魔法数字检查
(VOID)LOS_MuxLock(&g_cmdInfo.muxLock, LOS_WAIT_FOREVER);
if (g_cmdInfo.initMagicFlag != SHELL_INIT_MAGIC_FLAG) { //验证全局变量的有效性
(VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
PRINT_ERR("[%s] shell is not yet initialized!\n", __FUNCTION__);
......@@ -853,7 +853,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT
return OS_ERRNO_SHELL_CMDREG_PARA_ERROR;
}
}
//3.按键检查
//3.关键字检查 ;例如:'chmod 777 /home' ,此处检查 'chmod'的合法性
if (OsCmdKeyCheck(cmdKey) != TRUE) {
return OS_ERRNO_SHELL_CMDREG_CMD_ERROR;
}
......@@ -864,11 +864,11 @@ LITE_OS_SEC_TEXT_MINOR UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT
((strlen(cmdKey) == strlen(cmdItemNode->cmd->cmdKey)) &&
(strncmp((CHAR *)(cmdItemNode->cmd->cmdKey), cmdKey, strlen(cmdKey)) == 0))) {
(VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
return OS_ERRNO_SHELL_CMDREG_CMD_EXIST;
return OS_ERRNO_SHELL_CMDREG_CMD_EXIST;//已存在就退出
}
}
(VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
//5.正式创建命令,挂入链表
return OsCmdItemCreate(cmdType, cmdKey, paraNum, cmdProc);
return OsCmdItemCreate(cmdType, cmdKey, paraNum, cmdProc);//不存在就注册命令
}
......@@ -70,7 +70,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseParaGet(CHAR **value, const CHAR *paraTo
}
return LOS_OK;
}
//解析一个令牌
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseOneToken(CmdParsed *cmdParsed, UINT32 index, const CHAR *token)
{
UINT32 ret = LOS_OK;
......@@ -85,7 +85,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseOneToken(CmdParsed *cmdParsed, UINT32 in
return ret;
}
}
//参数限制,最多不能超过32个
if ((token != NULL) && (cmdParsed->paramCnt < CMD_MAX_PARAS)) {
tempLen = cmdParsed->paramCnt;
ret = OsCmdParseParaGet(&(cmdParsed->paramArray[tempLen]), token);
......@@ -96,7 +96,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseOneToken(CmdParsed *cmdParsed, UINT32 in
}
return ret;
}
//将shell命令按 ' ' 分开处理
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdTokenSplit(CHAR *cmdStr, CHAR split, CmdParsed *cmdParsed)
{
enum {
......@@ -123,7 +123,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdTokenSplit(CHAR *cmdStr, CHAR split, CmdParse
case STAT_TOKEN_IN:
if ((*p == split) && QUOTES_STATUS_CLOSE(quotes)) {
*p = '\0';
ret = OsCmdParseOneToken(cmdParsed, count++, token);
ret = OsCmdParseOneToken(cmdParsed, count++, token);//解析一个令牌
state = STAT_TOKEN_OUT;
}
break;
......@@ -144,7 +144,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdTokenSplit(CHAR *cmdStr, CHAR split, CmdParse
return ret;
}
//解析cmd命令
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParse(CHAR *cmdStr, CmdParsed *cmdParsed)
{
if ((cmdStr == NULL) || (cmdParsed == NULL) || (strlen(cmdStr) == 0)) {
......
......@@ -100,7 +100,7 @@ STATIC VOID ShellSaveHistoryCmd(const CHAR *string, ShellCB *shellCB)
(VOID)pthread_mutex_unlock(&shellCB->historyMutex);
return;
}
//发送解析事件
STATIC VOID ShellNotify(ShellCB *shellCB)
{
(VOID)LOS_EventWrite(&shellCB->shellEvent, SHELL_CMD_PARSE_EVENT);
......@@ -166,7 +166,7 @@ LITE_OS_SEC_TEXT_MINOR VOID ShellCmdLineParse(CHAR c, pf_OUTPUT outputFunc, Shel
(VOID)pthread_mutex_lock(&shellCB->keyMutex);
OsShellCmdPush(shellCB->shellBuf, shellCB->cmdKeyLink);//解析回车或换行
(VOID)pthread_mutex_unlock(&shellCB->keyMutex);
ShellNotify(shellCB);//通知输入命令完成
ShellNotify(shellCB);//通知任务解析shell命令
return;
} else if ((ch == '\b') || (ch == 0x7F)) { /* backspace or delete(0x7F) */ //遇到删除键
if ((shellCB->shellBufOffset > 0) && (shellCB->shellBufOffset < (SHOW_MAX_LEN - 1))) {
......
git add -A
git commit -m ' 对shell,控制台模块代码注解
git commit -m ' shell编辑,解析,执行三步走过程解析
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
博客输出站点(国内):http://weharmonyos.com
博客输出站点(国外):https://openharmony.github.io
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册