1 前言
通过Shell可以跟子系统打交道,子系统也可以提供很多接口供外部设置和读取信息。
下面就Shell的Kconfig配置、Shell的使用以及如何新建一个Shell命令展开。
可以说Shell是一窥内核究竟的管道,有了这个管道能使开发事半功倍。
有时为了开发和调试需求,还需要新增命令。
2 Shell相关配置
CONFIG_CONSOLE_SHELL是Shell子系统的开关,打开某一个模块的Shell,比如NET可以通过
CONFIG_NET_SHELL=y。
子模块的使能必须基于CONFIG_CONSOLE_SHELL。
如果要新增一个Shell配置,需要在使能CONFIG_CONSOLE_SHELL的情况下,在对应子模块中的Kconfig新增一个选项。
3 新增一个Shell命令
新增一个Shell命令,有如下步骤。
1. 新增一个选项,当然必须在定义CONFIG_CONSOLE_SHELL情况下才有效。
2. 通过SHELL_REGISTER
.注册一个新命令,包括命令名称和回调函数。
shell命令结构体:
struct shell_cmd { const char *cmd_name;---------------子命令名称 shell_cmd_function_t cb;------------子命令回调 const char *help;-------------------子命令帮助信息 };
3.1 kernel命令走读
kernel命令提供了获取
#if defined(CONFIG_INIT_STACKS) static int shell_cmd_stack(int argc, char *argv[]) { k_call_stacks_analyze(); return 0; } #endif struct shell_cmd kernel_commands[] = {-----------------------------------------shell_cmd类型的结构体数组 { "version", shell_cmd_version, "show kernel version" },-------------------- { "uptime", shell_cmd_uptime, "show system uptime in milliseconds" }, { "cycles", shell_cmd_cycles, "show system hardware cycles" }, #if defined(CONFIG_OBJECT_TRACING) && defined(CONFIG_THREAD_MONITOR) { "tasks", shell_cmd_tasks, "show running tasks" }, #endif #if defined(CONFIG_INIT_STACKS) { "stacks", shell_cmd_stack, "show system stacks" }, #endif { NULL, NULL, NULL } }; SHELL_REGISTER(SHELL_KERNEL, kernel_commands);---------------------------------通过SHELL_REGISTER注册shell这个命令,处理函数是kernel_commands。
4 Shell相关API
Shell子系统初始化SYS_INIT(shell_run, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT)(shell_service.c)。
#define SHELL_PROMPT "shell> " int shell_run(struct device *dev) { ARG_UNUSED(dev); shell_init(SHELL_PROMPT); return 0; } SYS_INIT(shell_run, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);---------------Shell子系统初始化 void shell_init(const char *str) { k_fifo_init(&cmds_queue); k_fifo_init(&avail_queue); line_queue_init(); prompt = str ? str : ""; k_thread_create(&shell_thread, stack, STACKSIZE, shell, NULL, NULL,---------------创建一个shell线程处理shell命令 NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); /* Register serial console handler */ #ifdef CONFIG_UART_CONSOLE uart_register_input(&avail_queue, &cmds_queue, completion); #endif #ifdef CONFIG_TELNET_CONSOLE telnet_register_input(&avail_queue, &cmds_queue, completion); #endif }