libvirt--->virsh 命令执行流程

本文以“ virsh  pool-info  vg10 ” 命令为例,分两个部分分析了virsh 命令的代码。(libvirt 版本为1.1.2  )


第一部分:综述virsh 命令的组成部分以及各结构体的关系;

第二部分:分析virsh  pool-info  vg10 命令的执行流程;


第一部分:

libvirt中的virsh  命令被分成了若干组,如:将对存储池(pool)进行操作的所有命令分到一个组,组名为:VSH_CMD_GRP_STORAGE_POOL。

再如:将对存储卷(volume )进行操作的所有命令分到一个组,组名为:VSH_CMD_GRP_STORAGE_VOL。

组的结构体如下:

struct _vshCmdGrp {
    const char *name;    /* name of group, or NULL for list end */
    const char *keyword; /* help keyword */
    const vshCmdDef *commands;
};

结构体中,其中第一个成员name 是组名,第三个成员commands指针指向了本组中的第一个命令,命令结构如下:

/*
 * vshCmdDef - command definition
 */
struct _vshCmdDef {
    const char *name;           /* name of command, or NULL for list end */
    bool (*handler) (vshControl *, const vshCmd *);    /* command handler */
    const vshCmdOptDef *opts;   /* definition of command options */
    const vshCmdInfo *info;     /* details about command */
    unsigned int flags;         /* bitwise OR of VSH_CMD_FLAG */
};

其中的name 是命令名,handler是处理此命令的具体函数(函数指针)。

1.1.2 版本中所有组定义在virsh.c 中,如下:

static const vshCmdGrp cmdGroups[] = {
    {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
    {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
    {VSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds},
    {VSH_CMD_GRP_IFACE, "interface", ifaceCmds},
    {VSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds},
    {VSH_CMD_GRP_NETWORK, "network", networkCmds},
    {VSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds},
    {VSH_CMD_GRP_SECRET, "secret", secretCmds},
    {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds},
    {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
    {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
    {VSH_CMD_GRP_VIRSH, "virsh", virshCmds},
    {NULL, NULL, NULL}
};

其中可见操作存储池的组,即 {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds}。

如上所述,其中的storagePoolCmds(第三个成员)  即指向操作存储池的组,它定义在virsh-pool.c文件中,如下:


const vshCmdDef storagePoolCmds[] = {
    {.name = "find-storage-pool-sources-as",
     .handler = cmdPoolDiscoverSourcesAs,
     .opts = opts_find_storage_pool_sources_as,
     .info = info_find_storage_pool_sources_as,
     .flags = 0
    },
    {.name = "find-storage-pool-sources",
     .handler = cmdPoolDiscoverSources,
     .opts = opts_find_storage_pool_sources,
     .info = info_find_storage_pool_sources,
     .flags = 0
    },
    {.name = "pool-autostart",
     .handler = cmdPoolAutostart,
     .opts = opts_pool_autostart,
     .info = info_pool_autostart,
     .flags = 0
    },
    {.name = "pool-build",
     .handler = cmdPoolBuild,
     .opts = opts_pool_build,
     .info = info_pool_build,
     .flags = 0
    },
    {.name = "pool-create-as",
     .handler = cmdPoolCreateAs,
     .opts = opts_pool_X_as,
     .info = info_pool_create_as,
     .flags = 0
    },
    {.name = "pool-create",
     .handler = cmdPoolCreate,
     .opts = opts_pool_create,
     .info = info_pool_create,
     .flags = 0
    },
    {.name = "pool-define-as",
     .handler = cmdPoolDefineAs,
     .opts = opts_pool_X_as,
     .info = info_pool_define_as,
     .flags = 0
    },
    {.name = "pool-define",
     .handler = cmdPoolDefine,
     .opts = opts_pool_define,
     .info = info_pool_define,
     .flags = 0
    },
    {.name = "pool-delete",
     .handler = cmdPoolDelete,
     .opts = opts_pool_delete,
     .info = info_pool_delete,
     .flags = 0
    },
    {.name = "pool-destroy",
     .handler = cmdPoolDestroy,
     .opts = opts_pool_destroy,
     .info = info_pool_destroy,
     .flags = 0
    },
    {.name = "pool-dumpxml",
     .handler = cmdPoolDumpXML,
     .opts = opts_pool_dumpxml,
     .info = info_pool_dumpxml,
     .flags = 0
    },
    {.name = "pool-edit",
     .handler = cmdPoolEdit,
     .opts = opts_pool_edit,
     .info = info_pool_edit,
     .flags = 0
    },
    {.name = "pool-info",
     .handler = cmdPoolInfo,
     .opts = opts_pool_info,
     .info = info_pool_info,
     .flags = 0
    },
    {.name = "pool-list",
     .handler = cmdPoolList,
     .opts = opts_pool_list,
     .info = info_pool_list,
     .flags = 0
    },
    {.name = "pool-name",
     .handler = cmdPoolName,
     .opts = opts_pool_name,
     .info = info_pool_name,
     .flags = 0
    },
    {.name = "pool-refresh",
     .handler = cmdPoolRefresh,
     .opts = opts_pool_refresh,
     .info = info_pool_refresh,
     .flags = 0
    },
    {.name = "pool-start",
     .handler = cmdPoolStart,
     .opts = opts_pool_start,
     .info = info_pool_start,
     .flags = 0
    },
    {.name = "pool-undefine",
     .handler = cmdPoolUndefine,
     .opts = opts_pool_undefine,
     .info = info_pool_undefine,
     .flags = 0
    },
    {.name = "pool-uuid",
     .handler = cmdPoolUuid,
     .opts = opts_pool_uuid,
     .info = info_pool_uuid,
     .flags = 0
    },
    {.name = NULL}
};

其中含有pool-info ,并且对应的处理函数是cmdPoolInfo() .


第二部分 :

virsh  pool-info  vg10 命令在gdb 下调试获得的流程如下:

main() 

  vshParseArgv(ctl, argc, argv)

vshCommandArgvParse(ctl, argc - optind, argv + optind); 

  vshCommandParse(ctl, &parser);

   vshCmddefSearch(tkdata)

vshCommandRun(ctl, ctl->cmd);

 


其中的函数vshCmddefSearch定义如下:

vshCmddefSearch(const char *cmdname)
{
    const vshCmdGrp *g;
    const vshCmdDef *c;
    for (g = cmdGroups; g->name; g++) {
        for (c = g->commands; c->name; c++) {
            if (STREQ(c->name, cmdname))
                return c;
        }
    }
    return NULL;
}


过程解析: pool-info作为命令名传到各级函数中,最后在vshCmddefSearch()中,首先定义了const vshCmdDef *c; 然后通过两个for循环遍历第一部分中定义的所有组和组中所有的命令,将每一个遍历到的命令赋值给c,需要注意的是:此时c就包含的下面结构体中的所有成员:

struct _vshCmdDef {
    const char *name;           /* name of command, or NULL for list end */
    bool (*handler) (vshControl *, const vshCmd *);    /* command handler */
    const vshCmdOptDef *opts;   /* definition of command options */
    const vshCmdInfo *info;     /* details about command */
    unsigned int flags;         /* bitwise OR of VSH_CMD_FLAG */
};

接下来  if (STREQ(c->name, cmdname))  语句很简单,如果当前遍历到的命令c 的第一个成员(即 名字)与命令名pool-info一样 ,则返回c ,由此即返回了处理此命令的handler .

回到main函数,即执行

vshCommandRun(ctl, ctl->cmd);

其中的ctl->cmd即是返回的命令。接下来vshCommandRun(ctl, ctl->cmd);中调用下面的语句进行具体的处理。

 cmd->def->handler(ctl, cmd);

至此,过程结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值