博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
qemu-QemuOpt
阅读量:4095 次
发布时间:2019-05-25

本文共 7815 字,大约阅读时间需要 26 分钟。

qemu参数解析:struct QemuOpt {
char *name; char *str; const QemuOptDesc *desc; union {
bool boolean; uint64_t uint; } value; QemuOpts *opts; QTAILQ_ENTRY(QemuOpt) next;};struct QemuOpts {
char *id; QemuOptList *list; Location loc; QTAILQ_HEAD(, QemuOpt) head; QTAILQ_ENTRY(QemuOpts) next;};struct QemuOptList {
const char *name; const char *implied_opt_name; bool merge_lists; QTAILQ_HEAD(, QemuOpts) head; QemuOptDesc desc[];};根据命令行格式:qemu-system-xxx [-options] [arg1, arg2, ...]以及上边的三个结构体,可知qemu对于参数的解析模式为:QemuOptList结构体将命令行参数中的optioins链接成链表形式,每个节点元素的类型为QemuOpts。每个option中可能会存在多个参数,QemuOpts将这些参数链接成链表形式,每个节点元素的类型为QemuOpt。因此,整体结构如下:QemuOptList(command line) | QemuOpts1------------------>QemuOpts2--->...(options) | | arg1--->arg2--->... arg1--->arg2--->...(arguments)关于QemuOptLists链表,主要分为两类,一类是vm_config;另一类是drive_config。因此,qemu提供了两种不同的接口:void qemu_add_opts(QemuOptsLists *list){
int entries, i; entries = ARRAY_SIZE(vm_config_groups); entries--; for (i = 0; i < entries; i++) {
if (i = 0; i < entries; i++) {
vm_config_groups[i] = list; return; } } fprinitf(stderr, "ran out of space in vm_config_groups"); abort();}void qemu_add_drive_opts(QemuOptsLists *list){
int entries, i; entries = ARRAY_SIZE(drive_config_groups); entries--; for (i = 0; i < entries; i++) {
if (drive_config_groups[i] == NULL) {
drive_config_groups[i] = list; } } fprintf(stderr, "ran out of space in drive_config_groups"); abort();}{
optind = 1; while (optind < argc) {
if (argv[optind][0] != '-') {
//如果首字符不为“-”,则表示该argv不是option字符 optind++; } else {
const QEMUOption *popt; popt = lookup_opt(argc, argv, &optarg, &optind); //获取与option相对应的QEMUOption结构体 switch(popt->index) {
case QEMU_OPTION_nouserconfig: userconfig = false; break; } } } //判断命令行中的option是否需要用户配置 if (userconfig) {
if (qemu_read_default_config_file() < 0) {
exit(1); } } //如果需要用户配置,则需要读取默认的配置文件 optind = 1; for (;;) {
if (optind >= argc) break; if (argv[optind][0] != '-') {
loc_set_cmdline(argv, optind, 1) drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS); } else {
const QEMUOption *popt; popt = lookup_opt(argc, argv, &optarg, &optind); if (!(popt->arch_mask &arch_type)) {
} switch(popt->index) {
case QEMU_OPTION_cpu: cpu_option = optarg; break; case QEMU_OPTION_kernel: qemu_opt_set(qemu_find_opts("machine"), NULL, "kernel", optarg, &error_abort); break; ... } } }}static const QEMUOption *lookup_opt(int argc, char **argv, const char **poptarg, int *poptind){
const QEMUOption *popt; int optind = *poptind; char *r = argv[optind]; const char *optarg; loc_set_cmdline(argv, optind, 1); optind++; if (r[1] == '-') r++; //如果option为“--x”,则将其处理为“-x” popt = qemu_options; //qemu_options变量是一个特殊的全局变量,其中存放qemu所有的options信息 for(;;) {
if (!popt->name) {
error_report("invalid option"); exit(1); } if (!strcmp(popt->name, r + 1)) break; popt++; } //判断命令行中的options是否存在。如果存在,则将该option相关的QEMUOption结构体返回 if (popt->flags & HAS_ARG) {
if (optind >= argc) {
error_report("requires an argument"); exit(1); } optarg = argv[optind++]; loc_set_cmdline(argv, optind - 2, 2); } else {
optarg = NULL; } //判断该option是否允许带有参数,如果允许,则读取该参数 *poptarg = optarg; *poptind = optind; return popt;}在代码中,变量qemu_options需要进一步解释。qemu_options变量原型为:static const QEMUOption qemu_options[] = {
{
"h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL },#define QEMU_OPTIONS_GENERATE_OPTIONS#include "qemu-options-wrapper.h" {
NULL },};qemu-optinons-wrapper.h {
#include "qemu-options.def" }qemu-options.def {
DEFHEADING(Standard options:)DEF("help", 0, QEMU_OPTION_h, "-h or -help display this help and exit\n", QEMU_ARCH_ALL)...}#elif define (QEMU_OPTIONS_GENERATE_OPTIONS)#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) { option, opt_arg, opt_enum, arch_mask },#define DEFHEADING(text)通过上边的代码可知,qemu所有的options变量存放在qemu_options全局数组当中。vm_config_groups数组存储不同类型的参数链表表头,因此结构为十字链表结构。drive_config_groups与其结构类似。如果解析的变量不是option,则调用drive_add接口来处理。QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr){
QemuOpts *opts; opts = drive_def(optstr); //根据optstr创建对应的QemuOpts结构体对象 if (!opts) {
return NULL; } if (type != IF_DEFAULT) {
qemu_opt_set(opts, "if", if_name[type], &error_abort); } if (index >= 0) {
qemu_opt_set_number(opts, "index", index, &error_abort); } if (file) qemu_opt_set(opts, "file", &error_abort); return opts;}QemuOpts *drive_def(const char *optstr){
return qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);}QemuOptsList *qemu_find_opts(const char *group){
QemuOptList *ret; Error *local_err = NULL; ret = find_list(vm_config_groups, group, &local_err); if (local_err) {
error_report_err(local_err); } return ret; //返回所需的链表}static QemuOptsList *find_list(QemuOptsList **lists, const char *group, Error **errp){
int i; for (i = 0; lists[i] != NULL; i++) {
if (strcmp(lists[i]->name, group) == 0) //从链表中查找名字与group相同的链表 break; } if (lists[i] == NULL) {
error_setg(errp, "There is no option group '%s'", group); } return lists[i]; //返回QemuOptList链表对象}QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params, bool permit_abbrev){
Error *err = NULL; QemuOpts *opts; bool help_wanted = false; opts = opts_parse(list, params, permit_abbrev, false, &help_wanted, &err); if (err) {
if (help_wanted) {
qemu_opts_print_help(list, true); error_free(err); } else {
error_report_err(err); } } return opts; //返回QemuOpts结构体对象}static QemuOpts *opts_parse(QemuOptsList *list, const char *params, bool permit_abbrev, bool defaults, bool *help_wanted, Error **errp){
const char *firstname; char *id = opts_parse_id(params); //解析params参数,判断该参数中是否存在“id=xx或id xx”字符串信息 //这里的params参数是由qemu自定义的宏参 QemuOpts *opts; assert(!permit_abbrev || list->implied_opt_name); firstname = permit_abbrev ? list->implied_opt_name : NULL; assert(!defaults || list->merge_lists); opts = qemu_opts_create(list, id, !defaults, errp); //创建QemuOpts结构体对象,并将QemuOpts与QemuOptList进行关联 g_free(id); if (opts == NULL) {
return NULL; } if (!opts_do_parse(opts, params, firstname, defaults, help_wanted, errp)) {
qemu_opts_del(opts); return NULL; } return opts;}bool qemu_opt_set(QemuOptList *list, const char *id, const char *name, const char *value, Error **errp){
QemuOpts *opts; opts = qemu_opts_create(list, id, 1, errp); if (!opts) {
return false; } return qemu_opt_set(opts, name, value, errp);}QemuOpts *qemu_opts_create(QemuOptList *list, const char *id, int fail_if_exists, Error **errp){
//创建QemuOpt结构体对象,进行赋值,链表操作,并与QemuOptList进行关联 QemuOpts *opts = NULL; if (id) {
... } else if (list->merge_lists) {
... } opts = g_malloc0(sizeof(*opts)); opts->id = g_strdup(id); opts->list = list; loc_save(&opts->loc); QTAILQ_INIT(&opts->head); QTAILQ_INSERT_TAIL(&list->head, opts, next); return opts;}bool qemu_opt_set(QemuOpts *opts, const char *name, const char *value, Error **errp){
QemuOpt *opt = opt_create(opts, name, g_strdup(value), false); if (!opt_validate(opt, NULL, errp)) {
qemu_opt_del(opt); return false; } return true;}static QemuOpt *opt_create(QemuOpts *opts, const char *name, char *value, bool prepend){
//创建QemuOpt结构体对象,进行赋值,链表操作,并与QemuOpts进行关联 QemuOpt *opt = g_malloc0(sizeof(*opt)); opt->name = g_strdup(name); opt->str = value; opt->opts = opts; if (prepend) {
QTAILQ_INSERT_HEAD(&opts->head, opt, next); } else {
QTAILQ_INSERT_TAIL(&opts->head, opt, next); } return opt;}

转载地址:http://npxii.baihongyu.com/

你可能感兴趣的文章
解决SimpleDateFormat线程安全问题NumberFormatException: multiple points
查看>>
MySQL数据库存储引擎简介
查看>>
处理Maven本地仓库.lastUpdated文件
查看>>
Kafka | 请求是怎么被处理的?
查看>>
Java并发编程1-线程池
查看>>
CentOS7,玩转samba服务,基于身份验证的共享
查看>>
计算机网络-网络协议模型
查看>>
计算机网络-OSI各层概述
查看>>
Java--String/StringBuffer/StringBuilder区别
查看>>
mySQL--深入理解事务隔离级别
查看>>
分布式之redis复习精讲
查看>>
数据结构与算法7-栈
查看>>
线性数据结构学习笔记
查看>>
数据结构与算法14-跳表
查看>>
Java并发编程 | 一不小心就死锁了,怎么办?
查看>>
(python版)《剑指Offer》JZ01:二维数组中的查找
查看>>
(python版)《剑指Offer》JZ06:旋转数组的最小数字
查看>>
(python版)《剑指Offer》JZ13:调整数组顺序使奇数位于偶数前面
查看>>
(python版)《剑指Offer》JZ28:数组中出现次数超过一半的数字
查看>>
(python版)《剑指Offer》JZ30:连续子数组的最大和
查看>>