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

系列文章目录

第九章 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系统分析之启动篇》系列文章。

bash 复制代码
..\qemu\8.2.2-qkd\qemu-system-x86_64.exe -cpu "Penryn" -M  "q35,accel=whpx" -m "6G" -nodefaults

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

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

c 复制代码
int qemu_init(int argc, char **argv)
{
...
    suspend_mux_open();

    qemu_disable_default_devices();
    qemu_setup_display();
    qemu_create_default_devices();
...
}

qemu_setup_display()

将非必要的设备关闭后,系统将建立显示输出,代码如下:

c 复制代码
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;
    }

    qemu_display_early_init(&dpy);
}

此操作完成显示设备的早期初始化工作,我们添加跟踪调试代码,最终代码如下:

c 复制代码
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);
}

调试输出如下:

bash 复制代码
[4516]../system/vl.c/qemu_init(3783):
[4516]../system/vl.c/qemu_setup_display(1383):
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(225):type=[2]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(226):has_full_screen=[0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(227):full_screen=[0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(228):has_window_close=[0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(229):window_close=[0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(230):has_show_cursor=[0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(231):show_cursor=[0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(232):has_gl=[1]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(256):u.egl_headless=[00007ff76f7f9fe0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayEGLHeadless(148):rendernode=[(null)]
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(270):u.sdl=[00007ff76f7f9fe0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplaySDL(183):has_grab_mod=[0]
[4516]../util/huedbg-display.c/huedbg_dump_DisplaySDL(184):grab_mod=[0]
[4516]../system/vl.c/qemu_setup_display(1385):
[4516]../ui/console.c/qemu_display_early_init(1668):
[4516]../util/huedbg-display.c/huedbg_dump_DisplayType(44):[0]=DISPLAY_TYPE_DEFAULT
[4516]../util/huedbg-display.c/huedbg_dump_DisplayType(45):[1]=DISPLAY_TYPE_NONE
[4516]../util/huedbg-display.c/huedbg_dump_DisplayType(51):[2]=DISPLAY_TYPE_SDL
[4516]../util/huedbg-display.c/huedbg_dump_DisplayType(54):[3]=DISPLAY_TYPE_EGL_HEADLESS
[4516]../util/huedbg-display.c/huedbg_dump_DisplayType(69):[4]=DISPLAY_TYPE__MAX
[4516]../ui/console.c/qemu_display_early_init(1670):
[4516]../util/huedbg-display.c/huedbg_dump_QemuDisplay(288):type=[2]
[4516]../util/huedbg-display.c/huedbg_dump_QemuDisplay(289):early_init=[00007ff76e7f04e0]
[4516]../util/huedbg-display.c/huedbg_dump_QemuDisplay(290):init=[00007ff76e7f08e0]
[4516]../util/huedbg-display.c/huedbg_dump_QemuDisplay(291):vc=[(null)]
[4516]../ui/console.c/qemu_display_early_init(1672):
[4516]../system/vl.c/qemu_init(3785):

根据调试的输出信息可知:

1、显示类型为 SDL

bash 复制代码
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(225):type=[2]
...
[4516]../util/huedbg-display.c/huedbg_dump_DisplayType(51):[2]=DISPLAY_TYPE_SDL

2、开启了 OpenGL 支持

bash 复制代码
[4516]../util/huedbg-display.c/huedbg_dump_DisplayOptions(232):has_gl=[1]

此项跟 -display 的设置有关,我们的启动项设置如下:

bash 复制代码
..\qemu\8.2.2-qkd\qemu-system-x86_64.exe -cpu "Penryn" -M  "q35,accel=whpx,smm=off" -m "6G" -display "sdl,gl=on" -audio "sdl,model=hda" -vga "std" -L "data" -nodefaults```

其中的 -display 项中有 "gl=on" 选项,因此可以看到显示设备选项中对应的设置也打开了。


qemu_create_default_devices()


总结

以上分析了系统初始化过程中显示设备的初始化过程。

相关推荐
美好的事情总会发生3 分钟前
32.768kHz晶振详解:作用、特性及与其他晶振的区别
嵌入式硬件·硬件工程·智能硬件
沧浪之水!14 分钟前
【Linux网络】:套接字之UDP
linux·网络·udp
BranH15 分钟前
Linux系统中命令设定临时IP
linux·运维·服务器
秋风起,再归来~33 分钟前
【Linux庖丁解牛】—进程优先级!
linux·运维·服务器
cosX+sinY1 小时前
ubuntu 20.04 编译运行lio-sam,并保存为pcd
linux·ubuntu·机器人
Lary_Rock2 小时前
Android 编译问题 prebuilts/clang/host/linux-x86
android·linux·运维
熬夜学编程的小王2 小时前
【Linux篇】理解信号:如何通过信号让程序听从操作系统的指令
linux·信号产生·软件条件产生信号
子非衣2 小时前
Windows云主机远程连接提示“出现了内部错误”
服务器·windows
国科安芯2 小时前
面向高性能运动控制的MCU:架构创新、算法优化与应用分析
单片机·嵌入式硬件·安全·架构·机器人·汽车·risc-v
绵绵细雨中的乡音2 小时前
Linux进程学习【基本认知】
linux·运维·学习