顾名思义动态命令即是可以动态变化的命令,Zephyr的shell系统提供一种机制,可以在运行时根据不同的情况提供给shell系统不同的子命令,已满足在不同场景下shell交互界面提供出不同命令。例如当网络没有连接时shell界面中只能看到connect的命令,连接成功后只能看到disconnect的命令。
使用方法
动态子命令由SHELL_DYNAMIC_CMD_CREATE
生成1
SHELL_DYNAMIC_CMD_CREATE(name, get)
name – [in] 动态命令入口.
get – [in] 一个
typedef void (*shell_dynamic_get)(size_t idx, struct shell_static_entry *entry)
类型的函数,根据idx
返回不同的struct shell_static_entry
类型的命令入口参数。struct shell_static_entry
和SHELL_CMD_ARG
指定的静态命令格式一样,指定命令符号,帮助信息,子命令入口,命令函数,和参数个数1
2
3
4struct shell_static_args {
uint8_t mandatory; /*!< 必选参数个数. */
uint8_t optional; /*!< 可选参数个数. */
};
1 | struct shell_static_entry { |
从上面看到get函数返回的shell命令入口和静态命令对应的参数一模一样, 参考Zephyr shell系统使用指南-添加命令
示例
如下代码片段演示了如何添加一个动态子命令:
准备一个
typedef void (*shell_dynamic_get)(size_t idx, struct shell_static_entry *entry)
类型的动态命令获取函数:1
2
3
4
5
6
7
8
9
10
11
12
13static void dynamic_cmd_get(size_t idx, struct shell_static_entry *entry)
{
if(idx<dynamic_cmd_num){
entry->syntax = cmd_name_flag? change_name[idx]:dynamic_entrys[idx].syntax;
entry->handler = dynamic_entrys[idx].handler;
entry->subcmd = dynamic_entrys[idx].subcmd;
entry->help = dynamic_entrys[idx].help;
entry->args.mandatory = dynamic_entrys[idx].args.mandatory;
entry->args.optional = dynamic_entrys[idx].args.optional;
}else{
entry->syntax = NULL;
}
}生成为动态子命令
dynamic_set
1
SHELL_DYNAMIC_CMD_CREATE(dynamic_set, dynamic_cmd_get);
将
dynamic_set
注册到根命令中1
2SHELL_CMD_REGISTER(shell_dynamic, &dynamic_set,
"Sample dynamic command usage.", NULL);
根命令shell_dynamic的子命令集为dynamic_set
,子命令集中有哪些子命令是由dynamic_cmd_get
的输出决定。shell系统在遍历根命令shell_dynamic的子命令时,传入参数idx
从0开始每次加一的循环调用dynamic_cmd_get
,直到输出的entry->syntax
为空。在上面的示例代码中动态子命令的个数由dynamic_cmd_num
决定,默认情况下就是dynamic_entrys[]
中的命令入口数量:
1 | /* 动态命令数组 */ |
开机后在shell中输入shell_dynamic
后按tab后可以看到所有的子命令
1 | uart:~$ shell_dynamic |
可以在运行时改变dynamic_cmd_num
的大小达到改变shell_dynamic的子命令数量,例如total子命令就可以达到这一目的,它对应的命令函数如下:
1 | static int cmd_dynamic_total(const struct shell *sh, size_t argc, char **argv) |
如果执行shell命令shell_dynamic total 1,cmd_dynamic_total
被调用将dynamic_cmd_num
修改为3,此时在shell中输入shell_dynamic后按tab后就只能看到只剩3个子命令:
1 | uart:~$ shell_dynamic |
也可以在运行时通过改变cmd_name_flag
变量的值,让动态子命令的syntax
发生改变,达到动态改变动态子命令符号的目的。例如执行shell_dynamic new_name后cmd_name_flag
被修改为1,dynamic_cmd_get
输出的syntax
将使用change_name
的内容
1 | char * change_name[] = { |
此时在shell中输入shell_dynamic后按tab后,看到的就是新的子命令名称
1 | uart:~$ shell_dynamic |
当然也可以修改dynamic_entrys
的内容达到添加和删除动态子命令的目的,或者是修改其中的子命令函数达到修改子命令功能的目的。
参考
https://docs.zephyrproject.org/latest/services/shell/index.html