【QEMU系统分析之实例篇(十二)】

发布于:2024-05-05 ⋅ 阅读:(33) ⋅ 点赞:(0)

系列文章目录

第十二章 QEMU系统仿真的机器创建分析实例



前言

本文以 QEMU 8.2.2 为例,分析其作为系统仿真工具的工作过程,并为读者展示各种 QEMU 系统仿真的启动配置实例。
本文读者需要具备一定的 QEMU 系统仿真使用经验,并对 C 语言编程有一定了解。


一、QEMU是什么?

QEMU 是一个通用且开源的机器模拟器和虚拟机。
其官方主页是:https://www.qemu.org/


二、QEMU系统仿真的机器创建分析实例

1.系统仿真的命令行参数

QEMU 作为系统仿真工具,其入口代码在 system/main.c 文件中,初始化函数 qemu_init() 的实现在 system/vl.c 文件中。
前文完成创建目标机器的过程分析,本文将继续后续运行过程的分析,读者需要对 QEMU 系统启动过程的程序代码有所了解,相关内容可以参考《QEMU系统分析之启动篇》系列文章。

..\qemu\8.2.2-qkd\qemu-system-x86_64.exe -cpu "Penryn" -M  "q35,accel=whpx,smm=off" -m "6G" -display "sdl" -audio "sdl,model=hda" -vga "std" -L "data"

2.完成默认设备的设置工作

这部分代码在 system/vl.c 文件中,实现如下:

int qemu_init(int argc, char **argv)
{
...
    qemu_disable_default_devices();
    qemu_setup_display();
    qemu_create_default_devices();
...
}

前文分析了创建显示输出和默认设备的过程,本文将去掉 -nodefaults 命令行参数,看看系统默认会创建哪些设备。


qemu_setup_display()

修改后的调试代码如下:

static void qemu_setup_display(void)
{
    if (dpy.type == DISPLAY_TYPE_DEFAULT && !display_remote) {
        if (!qemu_display_find_default(&dpy)) {
            dpy.type = DISPLAY_TYPE_NONE;
#if defined(CONFIG_VNC)
            vnc_parse("localhost:0,to=99,id=default");
            display_remote++;
#endif
        }
    }
    if (dpy.type == DISPLAY_TYPE_DEFAULT) {
        dpy.type = DISPLAY_TYPE_NONE;
    }

    HUEDBG("\n");
    huedbg_dump_DisplayOptions(&dpy, 3);
    HUEDBG("\n");
    qemu_display_early_init(&dpy);
}

qemu_create_default_devices()

修改后的调试代码如下:

static void qemu_create_default_devices(void)
{
    MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
    const char *vc = qemu_display_get_vc(&dpy);
    HUEDBG("vc=%s\n", vc);
    huedbg_dump_DisplayOptions(&dpy, 1);

    if (is_daemonized()) {
        /* According to documentation and historically, -nographic redirects
         * serial port, parallel port and monitor to stdio, which does not work
         * with -daemonize.  We can redirect these to null instead, but since
         * -nographic is legacy, let's just error out.
         * We disallow -nographic only if all other ports are not redirected
         * explicitly, to not break existing legacy setups which uses
         * -nographic _and_ redirects all ports explicitly - this is valid
         * usage, -nographic is just a no-op in this case.
         */
        if (nographic
            && (default_parallel || default_serial || default_monitor)) {
            error_report("-nographic cannot be used with -daemonize");
            exit(1);
        }
    }

    if (nographic) {
        if (default_parallel) {
            add_device_config(DEV_PARALLEL, "null");
        }
        if (default_serial && default_monitor) {
            add_device_config(DEV_SERIAL, "mon:stdio");
        } else {
            if (default_serial) {
                add_device_config(DEV_SERIAL, "stdio");
            }
            if (default_monitor) {
                monitor_parse("stdio", "readline", false);
            }
        }
    } else {
        if (default_serial) {
            add_device_config(DEV_SERIAL, vc ?: "null");
        }
        if (default_parallel) {
            add_device_config(DEV_PARALLEL, vc ?: "null");
        }
        if (default_monitor && vc) {
            monitor_parse(vc, "readline", false);
        }
    }

    if (default_net) {
        QemuOptsList *net = qemu_find_opts("net");
        qemu_opts_parse(net, "nic", true, &error_abort);
#ifdef CONFIG_SLIRP
        qemu_opts_parse(net, "user", true, &error_abort);
#endif
    }

    /* If no default VGA is requested, the default is "none".  */
    if (default_vga) {
        vga_model = get_default_vga_model(machine_class);
    }
    HUEDBG("vga_model=%s\n", vga_model);
    if (vga_model) {
        select_vgahw(machine_class, vga_model);
    }
}

static int serial_parse(const char *devname)
{
    int index = num_serial_hds;

    serial_hds = g_renew(Chardev *, serial_hds, index + 1);

    if (strcmp(devname, "none") == 0) {
        /* Don't allocate a serial device for this index */
        serial_hds[index] = NULL;
    } else {
        char label[32];
        snprintf(label, sizeof(label), "serial%d", index);

        serial_hds[index] = qemu_chr_new_mux_mon(label, devname, NULL);
        if (!serial_hds[index]) {
            error_report("could not connect serial device"
                         " to character backend '%s'", devname);
            return -1;
        }
    }
    num_serial_hds++;
    return 0;
}

此操作首先获取虚拟控制台设备的设置,然后根据命令行参数完成默认监视器、并口、串口和虚拟控制台的搭配,再获取默认网卡设置,最后配置 VGA 模型。我们添加跟踪调试代码,最终代码如下:

void qemu_display_early_init(DisplayOptions *opts)
{
    assert(opts->type < DISPLAY_TYPE__MAX);
    if (opts->type == DISPLAY_TYPE_NONE) {
        return;
    }
    if (dpys[opts->type] == NULL) {
        Error *local_err = NULL;
        int rv = ui_module_load(DisplayType_str(opts->type), &local_err);
        if (rv < 0) {
            error_report_err(local_err);
        }
    }
    if (dpys[opts->type] == NULL) {
        error_report("Display '%s' is not available.",
                     DisplayType_str(opts->type));
        exit(1);
    }
    HUEDBG("\n");
    huedbg_dump_DisplayType(1);
    HUEDBG("\n");
    huedbg_dump_QemuDisplay(dpys[opts->type], 3);
    HUEDBG("\n");
    if (dpys[opts->type]->early_init) {
        dpys[opts->type]->early_init(opts);
    }
}
...
static void qemu_setup_display(void)
{
    if (dpy.type == DISPLAY_TYPE_DEFAULT && !display_remote) {
        if (!qemu_display_find_default(&dpy)) {
            dpy.type = DISPLAY_TYPE_NONE;
#if defined(CONFIG_VNC)
            vnc_parse("localhost:0,to=99,id=default");
            display_remote++;
#endif
        }
    }
    if (dpy.type == DISPLAY_TYPE_DEFAULT) {
        dpy.type = DISPLAY_TYPE_NONE;
    }

    huedbg_dump_DisplayOptions(&dpy, 3);
    qemu_display_early_init(&dpy);
}

3.调试输出

[10320]../system/vl.c/qemu_init(2846):
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptsList(183):<<<deep>>>=[9] list=[00007ff67a53f5c0]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptsList(185):name=[drive]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptsList(186):implied_opt_name=[(null)]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptsList(187):merge_lists=[0]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptsList(188):head=[00007ff67a53f5d8]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptsList(192):desc=[00007ff67a53f5e8]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(160):<<<deep>>>=[8] desc=[00007ff67a53f5e8]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(162):name=[(null)]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(163):type=[0]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptType(116):<<<deep>>>=[7] idx=[0]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptType(127):[0]=QEMU_OPT_STRING
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(167):help=[(null)]
[10320]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(168):def_value_str=[(null)]
[10320]../system/vl.c/qemu_init(2848):
[10320]../system/vl.c/qemu_init(3799):
[10320]../system/vl.c/qemu_create_default_devices(1399):vc=vc:80Cx24C
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(276):<<<deep>>>=[1]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(278):type=[2]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayType(43):<<<deep>>>=[0] idx=[2]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayType(77):[2]=DISPLAY_TYPE_SDL
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(282):has_full_screen=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(283):full_screen=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(284):has_window_close=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(285):window_close=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(286):has_show_cursor=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(287):show_cursor=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(288):has_gl=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(289):gl=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(313):u.egl_headless=[00007ff67b15ffe0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayEGLHeadless(194):<<<deep>>>=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayEGLHeadless(196):rendernode=[(null)]
[10320]../util/huedbg-display.c/huedbg_dump_DisplayOptions(327):u.sdl=[00007ff67b15ffe0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplaySDL(233):<<<deep>>>=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplaySDL(235):has_grab_mod=[0]
[10320]../util/huedbg-display.c/huedbg_dump_DisplaySDL(236):grab_mod=[0]
[10320]../system/vl.c/qemu_create_default_devices(1457):vga_model=std
[10320]../qom/object.c/object_class_by_name(1095):enter
[10320]../qom/object.c/type_table_lookup(103):lookup type(VGA) in hash table
[10320]../qom/object.c/object_class_by_name(1105):class(VGA) return
[10320]../system/vl.c/qemu_init(3801):
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(92):<<<deep>>>=[1] conf=[000002729560f430]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(94):type=[1]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config_type(31):<<<deep>>>=[0] idx=[1]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config_type(48):[1]=DEV_SERIAL
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(98):cmdline=[vc:80Cx24C]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(99):loc=[p(000002729560f440)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(100):next=[p(000002729560f458)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(101):next.tqe_next=[000002729560e7f0]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(92):<<<deep>>>=[1] conf=[000002729560e7f0]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(94):type=[2]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config_type(31):<<<deep>>>=[0] idx=[2]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config_type(52):[2]=DEV_PARALLEL
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(98):cmdline=[vc:80Cx24C]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(99):loc=[p(000002729560e800)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(100):next=[p(000002729560e818)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(101):next.tqe_next=[0000000000000000]
[10320]../system/vl.c/qemu_init(3805):
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_configs(134):<<<deep>>>=[1] device_configs=[p(00007ff67a480cc0)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_configs(136):device_configs.tqh_first=[000002729560f430]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(92):<<<deep>>>=[0] conf=[000002729560f430]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(94):type=[1]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(98):cmdline=[vc:80Cx24C]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(99):loc=[p(000002729560f440)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(100):next=[p(000002729560f458)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(101):next.tqe_next=[000002729560e7f0]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(92):<<<deep>>>=[0] conf=[000002729560e7f0]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(94):type=[2]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(98):cmdline=[vc:80Cx24C]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(99):loc=[p(000002729560e800)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(100):next=[p(000002729560e818)]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_config(101):next.tqe_next=[0000000000000000]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_configs(141):device_configs.tqh_circ.tql_next=[000002729560f430]
[10320]D:/msys64/home/yuhui/gitee/mingw-qemu/util/huedbg_inline-device_config.c/huedbg_dump_device_configs(142):device_configs.tqh_circ.tql_prev=[000002729560e818]
[10320]../system/vl.c/qemu_init(3807):```

总结

以上分析了系统初始化过程中创建显示输出和默认设备的过程。


网站公告

今日签到

点亮在社区的每一天
去签到