【无标题】

lubanlite一段有意思的代码

一段关于控制台注册的代码实现。代码来源:Airchip Luban-Lite
首先是注册代码的定义:

/********************************************************
 * 注册控制台命令时的编译器属性定义
 * __attribute__((used)): 告诉编译器该函数或变量是实际使用到的,即使没有引用也要保留
 * __attribute__((section(".tinyspl.console.cmd"))): 告诉编译器将该函数或变量放到.tinyspl.console.cmd段中
 ********************************************************/
#define __console_init \
    __attribute__((used)) __attribute__((section(".tinyspl.console.cmd")))

/********************************************************
 * 控制台命令初始化结构体定义
 * cmdname: 命令名称
 * proc: 命令处理函数
 * mode: 命令模式,0表示普通模式,1表示后台模式
 * initialized: 是否已经初始化
 * help: 命令帮助信息
 ********************************************************/
struct console_init_cmd {
    const char *cmdname;
    int (*proc)(int argc, char **argv);
    uint8_t mode;
    bool initialized;
    const char *help;
};

/********************************************************
 * 控制台命令注册宏定义
 * _cmd: 命令名称
 * _proc: 命令处理函数
 * _help: 命令帮助信息
 ********************************************************/
#define CONSOLE_CMD(_cmd, _proc, _help)                                      \
    __console_init struct console_init_cmd console_init_cmd_##_cmd = {       \
        .cmdname = #_cmd, .proc = _proc, .initialized = false, .help = _help \
    };

使用的时候,首先调用console_init遍历整个.tinyspl.console.cmd

/**********************************
 * 控制台初始化函数
 **********************************/
void console_init(void)
{
    //命令起始地址和结束地址。
    //其中__console_init_start和__console_init_start是由编译器自动生成的,
    //用来存放所有的控制台初始化命令。
	struct console_init_cmd *cmd_start =
		(struct console_init_cmd *)&__console_init_start;
	struct console_init_cmd *cmd_end =
		(struct console_init_cmd *)&__console_init_start;
	struct console_init_cmd *p;

    if (!(g_console = malloc(sizeof(struct tiny_console))))
        return;

    memset(g_console, 0, sizeof(struct tiny_console));

    console_set_prompt(g_console, CONSOLE_PROMPT);
    console_set_sysname(g_console, CONSOLE_SYSNAME);
    //向控制台注册基本命令
    console_register_cmd("help", console_help, "Show all commands.");
    console_register_cmd("history", console_history, "Show history.");
    console_register_cmd("version", console_version, "Show version.");

	for (p = cmd_start; p < cmd_end; p++) {
		if (p->initialized)
			continue;
        //向控制台注册.tinyspl.console.cmd段中定义的所有命令
		console_register_init_cmds(p->cmdname);
	}

    return;
}

其中__console_init_start和__console_init_start在链接文件中定义

 .data : {
  . = ALIGN(0x8) ;
  __data_start__ = . ;
  __sdata = . ;
	.......
  *(.gcc_except_table)
  *(.gcc_except_table*)
  . = ALIGN(8) ;
  __console_init_start = .;	//段起始地址
  KEEP(*(.tinyspl.console.cmd))
  . = ALIGN(8) ;
  __console_init_end = .;	//段结束地址
  __global_pointer$ = .;
	......
  __edata = .;
  __data_end__ = .;
  . = ALIGN(0x8) ;

注册函数就是使用一个链表,保存所有的命令,和命令的入口函数。
查找函数就是比较命令名称,返回命令对应的结构体。

struct console_cmd *console_find_cmd_by_name(const char *name);
struct console_cmd *console_register_cmd(const char *cmd,
                                         int (*proc)(int, char **),
                                         const char *help);

使用:在其他任何地方都可以使用CONSOLE_CMD注册一条命令(App)和入口函数,然后就可以通过控制台来运行这段代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值