qemu参数解析过程

引言;本文内容主要以分析源码为主,顺着主要代码的逻辑进行梳理,不涉及架构部分

调试命令

ubuntu@VM-8-16-ubuntu:~/qemu$ gdb --args aarch64-softmmu/qemu-system-aarch64  \
			-machine virt \
			-cpu cortex-a57 \
			-m 2048 \
			-nographic

解析参数的代码位于:vl.c

// vl.c

int main(int argc, char **argv, char **envp)
{
   

开始是多个QemuOptsList结构体数组初始化

    qemu_add_opts(&qemu_drive_opts);
    qemu_add_drive_opts(&qemu_legacy_drive_opts);
    qemu_add_drive_opts(&qemu_common_drive_opts);
    qemu_add_drive_opts(&qemu_drive_opts);
    qemu_add_drive_opts(&bdrv_runtime_opts);
    qemu_add_opts(&qemu_chardev_opts);
    qemu_add_opts(&qemu_device_opts);
    qemu_add_opts(&qemu_netdev_opts);
    qemu_add_opts(&qemu_nic_opts);
    qemu_add_opts(&qemu_net_opts);
    qemu_add_opts(&qemu_rtc_opts);
    qemu_add_opts(&qemu_global_opts);
    qemu_add_opts(&qemu_mon_opts);
    qemu_add_opts(&qemu_trace_opts);
    qemu_add_opts(&qemu_option_rom_opts);
    qemu_add_opts(&qemu_machine_opts);
    qemu_add_opts(&qemu_accel_opts);
    qemu_add_opts(&qemu_mem_opts);
    qemu_add_opts(&qemu_smp_opts);
    qemu_add_opts(&qemu_boot_opts);
    qemu_add_opts(&qemu_add_fd_opts);
    qemu_add_opts(&qemu_object_opts);
    qemu_add_opts(&qemu_tpmdev_opts);
    qemu_add_opts(&qemu_realtime_opts);
    qemu_add_opts(&qemu_overcommit_opts);
    qemu_add_opts(&qemu_msg_opts);
    qemu_add_opts(&qemu_name_opts);
    qemu_add_opts(&qemu_numa_opts);
    qemu_add_opts(&qemu_icount_opts);
    qemu_add_opts(&qemu_semihosting_config_opts);
    qemu_add_opts(&qemu_fw_cfg_opts);

所有的QemuOptsList结构体数组存放于vm_config_groups(还有一个地方:drive_config_groups

// util/qemu-config.c

static QemuOptsList *vm_config_groups[48];
static QemuOptsList *drive_config_groups[5];

qemu_drive_opts为例

// blockdev.c

QemuOptsList qemu_drive_opts = {
   
    .name = "drive",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
    .desc = {
   
        /*
         * no elements => accept any params
         * validation will happen later
         */
        {
    /* end of list */ }
    },
};

来看看qemu_add_opts这个函数,可见就是将该数组加入vm_config_groups

// util/qemu-config.c

void qemu_add_opts(QemuOptsList *list)
{
   
    int entries, i;

    entries = ARRAY_SIZE(vm_config_groups);
    entries--; /* keep list NULL terminated */
    for (i = 0; i < entries; i++) {
   
        if (vm_config_groups[i] == NULL) {
   
            vm_config_groups[i] = list;
            return;
        }
    }
    fprintf(stderr, "ran out of space in vm_config_groups");
    abort();
}

qemu_add_drive_opts同理

// util/qemu-config.c

void qemu_add_drive_opts(QemuOptsList *list)
{
   
    int entries, i;

    entries = ARRAY_SIZE(drive_config_groups);
    entries--; /* keep list NULL terminated */
    for (i = 0; i < entries; i++) {
   
        if (drive_config_groups[i] == NULL) {
   
            drive_config_groups[i] = list;
            return;
        }
    }
    fprintf(stderr, "ran out of space in drive_config_groups");
    abort();
}

继续解析过程(它这里从1开始是因为忽略前面的qemu-system-aarch64

    /* second pass of option parsing */
    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)) {
   
                error_report("Option not supported for this target");
                exit(1);
            }

以运行指令为例,调用lookup_opt获得poptoptindoptarg的值

// vl.c

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++;
    /* Treat --foo the same as -foo.  */
    if (r[1] == '-')
        r++;
    popt = qemu_options;
    for(;;) {
   
        if (!popt->name) {
   
            error_report("invalid option");
            exit(1);
        }
        if (!strcmp(popt->name, r + 1))
            break;
        popt++;
    }
    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;
    }

    *poptarg = optarg;
    *poptind = optind;

    return popt;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妖怪喜欢风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值