• run_main_loop 到 cmd_process处理说明三


    一.  run_main_loop 到 cmd_process处理过程

    之前文章了解了 uboot的命令格式组成。本文简单分析下 cmd_process函数对 uboot命令的处理过程。

    本文继上一篇文章的学习,地址如下:

    uboot启动流程-run_main_loop 到 cmd_process处理说明二-CSDN博客

    二.  cmd_process函数处理命令过程

    1.  函数调用关系

    这里主要分析一下 uboot 的命令行处理过程。

    通过分析可知, cli_loop 函数通过一系列调用,最终调用 cmd_process函数处理命令。调用关系如下:

    2.  cmd_process函数处理命令过程

    cmd_process 函数定义在文件 common/command.c 中,函数内容如下:
    1. enum command_ret_t cmd_process(int flag, int argc, char * const argv[],
    2. int *repeatable, ulong *ticks)
    3. {
    4. enum command_ret_t rc = CMD_RET_SUCCESS;
    5. cmd_tbl_t *cmdtp;
    6. /* Look up command in command table */
    7. cmdtp = find_cmd(argv[0]);
    8. if (cmdtp == NULL) {
    9. printf("Unknown command '%s' - try 'help'\n", argv[0]);
    10. return 1;
    11. }
    12. /* found - check max args */
    13. if (argc > cmdtp->maxargs)
    14. rc = CMD_RET_USAGE;
    15. #if defined(CONFIG_CMD_BOOTD)
    16. /* avoid "bootd" recursion */
    17. else if (cmdtp->cmd == do_bootd) {
    18. if (flag & CMD_FLAG_BOOTD) {
    19. puts("'bootd' recursion detected\n");
    20. rc = CMD_RET_FAILURE;
    21. } else {
    22. flag |= CMD_FLAG_BOOTD;
    23. }
    24. }
    25. #endif
    26. /* If OK so far, then do the command */
    27. if (!rc) {
    28. if (ticks)
    29. *ticks = get_timer(0);
    30. rc = cmd_call(cmdtp, flag, argc, argv);
    31. if (ticks)
    32. *ticks = get_timer(*ticks);
    33. *repeatable &= cmdtp->repeatable;
    34. }
    35. if (rc == CMD_RET_USAGE)
    36. rc = cmd_usage(cmdtp);
    37. return rc;
    38. }

    cmd_process 函数 调用函数 find_cmd函数 在命令表中找到指定的命令, find_cmd 函数内容如下:
     
    1. cmd_tbl_t *find_cmd(const char *cmd)
    2. {
    3. cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd);
    4. const int len = ll_entry_count(cmd_tbl_t, cmd);
    5. return find_cmd_tbl(cmd, start, len);
    6. }

    参数 cmd 就是所查找的命令名字, uboot 中的命令表其实就是 cmd_tbl_t 结构体数组,通 ll_entry_star t 函数得到数组的第一个元素,也就是命令表起始地址。
    通过 ll_entry_count 函数得到数组长度,也就是命令表的长度。
    最终通过 find_cmd_tbl 函数在命令表中找到所需的命 令,每个命令都有一个 name 成员,所以将参数 cmd 与命令表中每个成员的 name 字段都对比 一下,如果相等的话就说明找到了这个命令,找到以后就返回这个命令。

      cmd_process 函数中,找到命令以后肯定就要执行这个命令了, 调用 cmd_call函数来执行具体的命令,cmd_call 函数内容如下:
    1. static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    2. {
    3. int result;
    4. result = (cmdtp->cmd)(cmdtp, flag, argc, argv);
    5. if (result)
    6. debug("Command failed, result=%d\n", result);
    7. return result;
    8. }

    在前面的分析中我们知道, cmd_tbl_t cmd 成员就是具体的命令处理函数,所以,cmd_call 函数中,第5行 调用 cmdtp cmd 成员来处理具体的命令,返回值为命令的执行结果。
    cmd_process 中会检测 cmd_tbl 的返回值,如果返回值为 CMD_RET_USAGE ,就会调用
    cmd_usage 函数输出命令的用法,其实就是输出 cmd_tbl_t usage 成员变量。

  • 相关阅读:
    1.let和const关键字
    服务器数据恢复—云服务器mysql数据库表被truncate的数据恢复案例
    YOLOv5白皮书-第Y6周:模型改进
    深度学习:模型训练过程中Trying to backward through the graph a second time解决方案
    智工教育:公务员考试这些知识点你会背了吗?
    B+树结构与索引<二> _ 索引页示例
    GIT特殊场景
    PHP SimpleXML
    webpack5 import动态导入实现按需加载并给文件统一命名
    Swagger-----knife4j框架
  • 原文地址:https://blog.csdn.net/wojiaxiaohuang2014/article/details/133751465