qemu 订阅
QEMU是一套由法布里斯·贝拉(Fabrice Bellard)所编写的以GPL许可证分发源码的模拟处理器,在GNU/Linux平台上使用广泛。Bochs,PearPC等与其类似,但不具备其许多特性,比如高速度及跨平台的特性,通过KQEMU这个闭源的加速器,QEMU能模拟至接近真实电脑的速度。目前,0.9.1及之前版本的qemu可以使用kqemu加速器。在qemu1.0之后的版本,都无法使用kqemu,主要利用qemu-kvm加速模块,并且加速效果以及稳定性明显好于kqemu。 展开全文
QEMU是一套由法布里斯·贝拉(Fabrice Bellard)所编写的以GPL许可证分发源码的模拟处理器,在GNU/Linux平台上使用广泛。Bochs,PearPC等与其类似,但不具备其许多特性,比如高速度及跨平台的特性,通过KQEMU这个闭源的加速器,QEMU能模拟至接近真实电脑的速度。目前,0.9.1及之前版本的qemu可以使用kqemu加速器。在qemu1.0之后的版本,都无法使用kqemu,主要利用qemu-kvm加速模块,并且加速效果以及稳定性明显好于kqemu。
信息
研发者
Fabrice Bellard
外文名
QEMU
用    途
模拟操作系统
中文名
虚拟操作系统模拟器
QEMU运作模式
QEMU有两种主要运作模式:* User mode模拟模式,亦即是用户模式。QEMU能启动那些为不 同中央处理器编译的Linux程序。而Wine及Dosemu是其主要目标。* System mode模拟模式,亦即是系统模式。QEMU能模拟整个电脑系统,包括中央处理器及其他周边设备。它使得为跨平台编写的程序进行测试及除错工作变得容易。其亦能用来在一部主机上虚拟数部不同虚拟电脑。QEMU的主体部份是在LGPL下发布的,而其系统模式模拟则是在GPL下发布;而kqemu这个加速器则是在免费但闭源的条件下发布的。使用kqemu可使QEMU能模拟至接近实机速度,但其在虚拟的操作系统是 Microsoft Windows 98或以下的情况下是无用的。
收起全文
精华内容
下载资源
问答
  • 基于Web的QEMU界面 该项目旨在在本地服务器上运行,并允许客户端连接并启动KVM加速的虚拟机。 该程序仅对QEMU的某些功能提供非常基本的支持。 客户端可以上载ISO并在服务器上创建原始磁盘映像,并且他们可以使用这些...
  • Qemu Windows 10 Botstrap使用Qemu(带有QXL驱动程序和外部桥接网络)在Linux机器上运行Windows 10。 开始吧 创建Windows 10文件夹并将其放置在虚拟驱动器中。 对于Windows 10,建议使用50G及更高容量。 mkdir -p ...
  • MacOS上的3D加速qemu 有什么用 如果您拥有Mac(x86或ARM),并希望拥有完整Linux桌面以进行开发或测试,那么您会发现拥有响应式桌面是一件好事。 多亏( ,图形加速。 我只是将其打包到易于安装的brew存储库中,而...
  • QEMU客座代理 适用于FreeBSD guest虚拟机的QEMU Guest Agent版本 警告!!! 此端口按“原样”提供。 某些命令不起作用,例如“ fsfreeze”。 我们尝试在FreeBSD上为vcpu和fs功能打补丁。 FreeBSD中的命令参考和...
  • SiFive Freedom QEMU系统仿真器 在SiFive,我们一直在分发针对Freedom RISC-V平台的工具的二进制发行包。 该存储库包含我们用来构建其中一些工具的脚本。 此仓库是Freedom Tools的一部分: : SiFive添加到原始...
  • qemu_esp32将tensilica esp32 cpu和一块板添加到qemu并转储rom以了解有关esp-idf的更多信息 QEMU中的ESP32。 本文档介绍了如何在qemu中添加esp32 cpu和简单的esp32板,以便在QEMU中运行使用SDK(esp-idf)编译的...
  • 运行带有QEMU的macOS x86_64上虚拟化的arm64 / aarch64 Linux Alpine。 需要安装qemu-system-aarch64 ,可以从Homebrew获得: brew install qemu 跑步: ./qemu-arm64.sh 首次运行时,它将复制user-data-init....
  • qemu-guest-agent的Docker映像 该docker映像提供基于centos的qemu-guest-agent。 如何建造 docker build -t ele / qemu-guest-agent:latest。 如何使用 该映像仅在运行容器的虚拟机内部有用。 它提供了,可以在运行...
  • 我对qemu的更改以实现传统的免费GPU传递。 只有一个适配器可以同时使用旧版vga区域。 这是在没有传统vga访问图形卡的情况下实现qemu gpu直通的尝试。 通过MMIO访问来替换对VGA寄存器的旧版IO访问。 对vga内存的旧版...
  • qemuconf - 具有配置文件支持的简单 qemu 启动器 概要 qemuconf [ -q exec ]配置文件[-- qemu-options ...] qemuconf [ -v ] 描述 qemuconf使用从配置文件编译的参数执行 qemu。 选项 -q exec设置默认二进制文件。 ...
  • QEMU

    万次阅读 多人点赞 2016-03-31 17:55:42
    QEMU 1: 使用QEMU创建虚拟机 一、QEMU简介 QEMU是一款开源的模拟器及虚拟机监管器(Virtual Machine Monitor, VMM)。QEMU主要提供两种功能给用户使用。一是作为用户态模拟器,利用动态代码翻译机制来执行...

    QEMU 1: 使用QEMU创建虚拟机

    一、QEMU简介

    QEMU是一款开源的模拟器及虚拟机监管器(Virtual Machine Monitor, VMM)。QEMU主要提供两种功能给用户使用。一是作为用户态模拟器,利用动态代码翻译机制来执行不同于主机架构的代码。二是作为虚拟机监管器,模拟全系统,利用其他VMM(Xen, KVM, etc)来使用硬件提供的虚拟化支持,创建接近于主机性能的虚拟机。

    用户可以通过不同Linux发行版所带有的软件包管理器来安装QEMU。如在Debian系列的发行版上可以使用下面的命令来安装:

    sudo apt-get install qemu

    或者在红帽系列的发行版上使用如下命令安装:

    sudo yum install qemu -y

    除此之外,也可以选择从源码安装。

    获取QEMU源码

    可以从QEMU官网上下载QEMU源码的tar包,以命令行下载2.0版本的QEMU为例:

    $wget http://wiki.qemu-project.org/download/qemu-2.0.0.tar.bz2
    $tar xjvf qemu-2.0.0.tar.bz2
    

    如果需要参与到QEMU的开发中,最好使用Git获取源码:

    $git clone git://git.qemu-project.org/qemu.git

    编译及安装

    获取源码后,可以根据需求来配置和编译QEMU。

    $cd qemu-2.0.0 //如果使用的是git下载的源码,执行cd qemu
    $./configure --enable-kvm --enable-debug --enable-vnc --enable-werror  --target-list="x86_64-softmmu"
    $make -j8
    $sudo make install
    

    configure脚本用于生成Makefile,其选项可以用./configure --help查看。这里使用到的选项含义如下:

    --enable-kvm:编译KVM模块,使QEMU可以利用KVM来访问硬件提供的虚拟化服务。
    --enable-vnc:启用VNC--enalbe-werror:编译时,将所有的警告当作错误处理。
    --target-list:选择目标机器的架构。默认是将所有的架构都编译,但为了更快的完成编译,指定需要的架构即可。
    

    二、基本原理

    QEMU作为系统模拟器时,会模拟出一台能够独立运行操作系统的虚拟机。如下图所示,每个虚拟机对应主机(Host)中的一个QEMU进程,而虚拟机的vCPU对应QEMU进程的一个线程。

    QEMU结构图

    系统虚拟化最主要是虚拟出CPU、内存及I/O设备。虚拟出的CPU称之为vCPU,QEMU为了提升效率,借用KVM、XEN等虚拟化技术,直接利用硬件对虚拟化的支持,在主机上安全地运行虚拟机代码(需要硬件支持)。虚拟机vCPU调用KVM的接口来执行任务的流程如下(代码源自QEMU开发者Stefan的技术博客):

    open("/dev/kvm")
    ioctl(KVM_CREATE_VM)
    ioctl(KVM_CREATE_VCPU)
    for (;;) {
         ioctl(KVM_RUN)
         switch (exit_reason) {
         case KVM_EXIT_IO:  /* ... */
         case KVM_EXIT_HLT: /* ... */
         }
    }
    

    QEMU发起ioctrl来调用KVM接口,KVM则利用硬件扩展直接将虚拟机代码运行于主机之上,一旦vCPU需要操作设备寄存器,vCPU将会停止并退回到QEMU,QEMU去模拟出操作结果。

    虚拟机内存会被映射到QEMU的进程地址空间,在启动时分配。在虚拟机看来,QEMU所分配的主机上的虚拟地址空间为虚拟机的物理地址空间。

    QEMU在主机用户态模拟虚拟机的硬件设备,vCPU对硬件的操作结果会在用户态进行模拟,如虚拟机需要将数据写入硬盘,实际结果是将数据写入到了主机中的一个镜像文件中。

    三、创建及使用虚拟机

    命令行创建及启动虚拟机

    成功安装QEMU之后便可创建自己的虚拟机。具体步骤如下:

    1, 使用qemu-img创建虚拟机镜像。虚拟机镜像用来模拟虚拟机的硬盘,在启动虚拟机之前需要创建镜像文件。

    [kelvin@kelvin tmp]$ qemu-img create -f qcow2 fedora.img 10G
    Formatting 'fedora.img', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off 
    [kelvin@kelvin tmp]$ ls
    fedora.img
    

    -f选项用于指定镜像的格式,qcow2格式是QEMU最常用的镜像格式,采用写时复制技术来优化性能。fedora.img是镜像文件的名字,10G是镜像文件大小。镜像文件创建完成后,可使用qemu-system-x86来启动x86架构的虚拟机:

    qemu-system-x86_64 fedora.img

    此时会弹出一个窗口来作为虚拟机的显示器,显示内容如下:

    QEMU虚拟机显示器输出

    因为fedora.img中并未给虚拟机安装操作系统,所以会提示“No bootable device”,无可启动设备。

    2, 准备操作系统镜像。

    可以从不同Linux发行版的官方网站上获取安装镜像,以fedora20为例:

    [kelvin@kelvin tmp]$ wget http://ftp6.sjtu.edu.cn/fedora/linux/releases/20/Live/x86_64/Fedora-Live-Desktop-x86_64-20-1.iso

    3, 检查KVM是否可用。

    QEMU使用KVM来提升虚拟机性能,如果不启用KVM会导致性能损失。要使用KVM,首先要检查硬件是否有虚拟化支持:

    [kelvin@kelvin ~]$ grep -E 'vmx|svm' /proc/cpuinfo

    如果有输出则表示硬件有虚拟化支持。其次要检查kvm模块是否已经加载:

    [kelvin@kelvin ~]$ lsmod | grep kvm
    kvm_intel             142999  0 
    kvm                   444314  1 kvm_intel
    

    如果kvm_intel/kvm_amd、kvm模块被显示出来,则kvm模块已经加载。最后要确保qemu在编译的时候使能了KVM,即在执行configure脚本的时候加入了–enable-kvm选项。

    4, 启动虚拟机安装操作系统。

    执行下面的命令启动带有cdrom的虚拟机:

    [kelvin@kelvin tmp]$ qemu-system-x86_64 -m 2048 -enable-kvm fedora.img -cdrom ./Fedora-Live-Desktop-x86_64-20-1.iso

    -m 指定虚拟机内存大小,默认单位是MB, -enable-kvm使用KVM进行加速,-cdrom添加fedora的安装镜像。可在弹出的窗口中操作虚拟机,安装操作系统,安装完成后重起虚拟机便会从硬盘(fedora.img)启动。之后再启动虚拟机只需要执行:

    [kelvin@kelvin tmp]$ qemu-system-x86_64 -m 2048 -enable-kvm fedora.img

    即可。

    图形界面创建及启动虚拟机

    命令行启动虚拟机比较繁琐,适合开发者,但对于普通用户来说,采用图形界面管理虚拟机则更为方便。采用图形界面管理QEMU虚拟机需要安装virt-manager,红帽系列的发行版只需要执行命令:

    $sudo yum install virt-manager -y

    安装完成后用root用户启动virt-manager:

    $su -
    #virt-manager
    

    启动后的界面如下图所示:

    virt-manager界面

    点击左上角电脑图标即可创建虚拟机。按照步骤操作即可完成对虚拟机的创建。



    QEMU 2: 参数解析

    一、使用gdb分析QEMU代码

    使用gdb不仅可以很好地调试代码,也可以利用它来动态地分析代码。使用gdb调试QEMU需要做一些准备工作:

    1, 编译QEMU时需要在执行configure脚本时的参数中加入–enable-debug。

    2, 从QEMU官方网站上下载一个精简的镜像——linux-0.2.img。linux-0.2.img只有8MB大小,启动后包含一些常用的shell命令,用于QEMU的测试。

    $wget http://wiki.qemu.org/download/linux-0.2.img.bz2
    $bzip2 -d ./linux-0.2.img.bz2
    

    3, 启动gdb调试QEMU:

    gdb --args qemu-system-x86_64 -enable-kvm -m 4096 -smp 4 linux-0.2.img

    -smp指定处理器个数。

    二、参数解析用到的数据结构

    QEMU系统模拟的主函数位于vl.c文件,无论是qemu-system-x86_64还是qemu-system-ppc64,都是从vl.c中的main函数开始执行。下面先介绍main函数涉及到的一些数据结构。

    QEMU链表

    QEMU的链表在include/qemu/queue.h文件中定义,分为四种类型:

    • 单链表(singly-linked list):单链表适用于大的数据集,并且很少有删除节点或者移动节点的操作,也适用于实现后进先出的队列。
    • 链表(list):即双向链表,除了头节点之外每个节点都会同时指向前一个节点和后一个节点。
    • 简单队列(simple queue):简单队列类似于单链表,只是多了一个指向链表尾的一个表头,插入节点的时候不仅可以像单链表那样将其插入表头或者某节点之后,还可以插入到链表尾。
    • 尾队列(tail queue):类似于简单队列,但节点之间是双向指向的。

    这里不一一介绍各种链表的用法,只通过NotifierList的定义来说明QEMU链表(list)的用法。在main函数的开头定义的DisplayState结构体使用到了NotifiereList,NotifierList就用到了链表。

    a. 表头及节点的定义

    定义表头需要用到QLIST_HEAD,定义如下:

     86 #define QLIST_HEAD(name, type)                                          \
     87 struct name {                                                           \
     88         struct type *lh_first;  /* first element */                     \
     89 }
    

    NotifierList就采用了QLIST_HEAD来定义表头:

     27 typedef struct NotifierList
     28 {
     29     QLIST_HEAD(, Notifier) notifiers;
     30 } NotifierList;
    

    定义节点需要用到QLIST_ENTRY,定义如下:

     94 #define QLIST_ENTRY(type)                                               \
     95 struct {                                                                \
     96         struct type *le_next;   /* next element */                      \
     97         struct type **le_prev;  /* address of previous next element */  \
     98 }
    

    Notifier的节点定义如下:

     21 struct Notifier
     22 {
     23     void (*notify)(Notifier *notifier, void *data);
     24     QLIST_ENTRY(Notifier) node;
     25 };
    

    b. 初始化表头

    初始化表头用到QLIST_INIT:

    103 #define QLIST_INIT(head) do {                                           \
    104         (head)->lh_first = NULL;                                        \
    105 } while (/*CONSTCOND*/0)
    

    初始化NotifierList就可以这样进行:

     19 void notifier_list_init(NotifierList *list)
     20 {
     21     QLIST_INIT(&list->notifiers);
     22 }
    

    c. 在表头插入节点

    将节点插入到表头使用QLIST_INSERT_HEAD:

    122 #define QLIST_INSERT_HEAD(head, elm, field) do {                        \
    123         if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
    124                 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
    125         (head)->lh_first = (elm);                                       \
    126         (elm)->field.le_prev = &(head)->lh_first;                       \
    127 } while (/*CONSTCOND*/0)
    

    插入Notifier到NotifierList:

     24 void notifier_list_add(NotifierList *list, Notifier *notifier)
     25 {
     26     QLIST_INSERT_HEAD(&list->notifiers, notifier, node);
     27 }
    

    d. 遍历节点

    遍历节点使用QLIST_FOREACH或者QLIST_FOREACH_SAFE,QLIST_FOREACH_SAFE是为了防止遍历过程中删除了节点,从而导致le_next被释放掉,中断了遍历。

    147 #define QLIST_FOREACH(var, head, field)                                 \
    148         for ((var) = ((head)->lh_first);                                \
    149                 (var);                                                  \
    150                 (var) = ((var)->field.le_next))
    151 
    152 #define QLIST_FOREACH_SAFE(var, head, field, next_var)                  \
    153         for ((var) = ((head)->lh_first);                                \
    154                 (var) && ((next_var) = ((var)->field.le_next), 1);      \
    155                 (var) = (next_var))
    

    NotifierList在执行所有的回调函数时就用到了QLIST_FOREACH_SAFE:

     34 void notifier_list_notify(NotifierList *list, void *data)
     35 {
     36     Notifier *notifier, *next;
     37 
     38     QLIST_FOREACH_SAFE(notifier, &list->notifiers, node, next) {
     39         notifier->notify(notifier, data);
     40     }
     41 }
    

    Error和QError

    为了方便的处理错误信息,QEMU定义了Error和QError两个数据结构。Error在qobject/qerror.c中定义:

    101 struct Error
    102 {
    103     char *msg;
    104     ErrorClass err_class;
    105 };
    

    包含了错误消息字符串和枚举类型的错误类别。错误类别有下面几个:

     139 typedef enum ErrorClass
     140 {
     141     ERROR_CLASS_GENERIC_ERROR = 0,
     142     ERROR_CLASS_COMMAND_NOT_FOUND = 1,
     143     ERROR_CLASS_DEVICE_ENCRYPTED = 2,
     144     ERROR_CLASS_DEVICE_NOT_ACTIVE = 3,
     145     ERROR_CLASS_DEVICE_NOT_FOUND = 4,
     146     ERROR_CLASS_K_V_M_MISSING_CAP = 5,
     147     ERROR_CLASS_MAX = 6,
     148 } ErrorClass;
    

    QEMU在util/error.c中定义了几个函数来对Error进行操作:

    error_set  //根据给定的ErrorClass以及格式化字符串来给Error分配空间并赋值
    error_set_errno  //除了error_set的功能外,将指定errno的错误信息追加到格式化字符串的后面
    error_copy  //复制Error           
    error_is_set   //判断Error是否已经分配并设置
    error_get_class  //获取Error的ErrorClass      
    error_get_pretty  //获取Error的msg
    error_free  //释放Error及msg的空间
    

    另外,QEMU定义了QError来处理更为细致的错误信息:

     22 typedef struct QError { 
     23     QObject_HEAD;
     24     Location loc;
     25     char *err_msg;
     26     ErrorClass err_class;
     27 } QError;
    

    QError可以通过一系列的宏来给err_msg及err_class赋值:

     39 #define QERR_ADD_CLIENT_FAILED \
     40     ERROR_CLASS_GENERIC_ERROR, "Could not add client"
     41 
     42 #define QERR_AMBIGUOUS_PATH \
     43     ERROR_CLASS_GENERIC_ERROR, "Path '%s' does not uniquely identify an object"
     44 
     45 #define QERR_BAD_BUS_FOR_DEVICE \
     46     ERROR_CLASS_GENERIC_ERROR, "Device '%s' can't go on a %s bus"
     47 
     48 #define QERR_BASE_NOT_FOUND \
     49     ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found"
    ...
    

    Location记录了出错的位置,定义如下:

     20 typedef struct Location {
     21     /* all members are private to qemu-error.c */
     22     enum { LOC_NONE, LOC_CMDLINE, LOC_FILE } kind;
     23     int num;
     24     const void *ptr;
     25     struct Location *prev;
     26 } Location;
    

    GMainLoop

    QEMU使用glib中的GMainLoop来实现IO多路复用,关于GMainLoop可以参考博客GMainLoop的实现原理和代码模型。由于GMainLoop并非QEMU本身的代码,本文就不重复赘述。

    三、QEMUOption、QemuOpt及QEMU参数解析

    QEMU定义了QEMUOption来表示执行qemu-system-x86_64等命令时用到的选项。在vl.c中定义如下:

    2123 typedef struct QEMUOption {
    2124     const char *name;   //选项名,如 -device, name的值就是device
    2125     int flags;  //标志位,表示选项是否带参数,可以是0,或者HAS_ARG(值为0x0001)
    2126     int index;  //枚举类型的值,如-device,该值就是QEMU_OPTION_device
    2127     uint32_t arch_mask;  //  选项支持架构的掩码
    2128 } QEMUOption;
    

    vl.c中维护了一个QEMUOption数组qemu_options来存储所有可用的选项,并利用qemu-options-wrapper.h和qemu-options.def来给该数组赋值。赋值语句如下:

    2130 static const QEMUOption qemu_options[] = {
    2131     { "h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL },
    2132 #define QEMU_OPTIONS_GENERATE_OPTIONS
    2133 #include "qemu-options-wrapper.h"
    2134     { NULL },
    2135 };
    

    #define QEMU_OPTIONS_GENERATE_OPTIONS选择qemu-options-wrapper.h的操作,qemu-options-wrapper.h可以进行三种操作:

    QEMU_OPTIONS_GENERATE_ENUM: 利用qemu-options.def生成一个枚举值列表,就是上面提到的QEMU_OPTION_device等
    QEMU_OPTIONS_GENERATE_HELP: 利用qemu-options.def生成帮助信息并输出到标准输出
    QEMU_OPTIONS_GENERATE_OPTIONS: 利用qemu-options.def生成一组选项列表
    

    可以通过下面的方法来展开qemu-options-wrapper.h来查看上述操作的结果,以生成选项为例。

    1. 在qemu-options-wrapper.h第一行写入#define QEMU_OPTIONS_GENERATE_OPTIONS.
    2. 执行命令gcc -E -o options.txt qemu-options-wrapper.h
    3. 查看文件options.txt即可

    给qemu_options数组赋值后,QEMU就有了一个所有可用选项的集合。之后在vl.c中main函数的一个for循环根据这个集合开始解析命令行。for循环的框架大致如下:

      1     for(;;) {
      2         if (optind >= argc)
      3             break;
      4         if (argv[optind][0] != '-') {
      5         hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
      6         } else {
      7             const QEMUOption *popt;
      8 
      9             popt = lookup_opt(argc, argv, &optarg, &optind);
     10             if (!(popt->arch_mask & arch_type)) {
     11                 printf("Option %s not supported for this target\n", popt->name);
     12                 exit(1);
     13             }
     14             switch(popt->index) {
     15             case QEMU_OPTION_M:
     16             ......
     17             case QEMU_OPTION_hda:
     18             ......  
     19             case QEMU_OPTION_watchdog:
     20             ......
     21             default:
     22                 os_parse_cmd_args(popt->index, optarg);
     23             }   
     24         }
     25     }
    

    QEMU会把argv中以'-'开头的字符串当作选项,然后调用lookup_opt函数到qemu_options数组中查找该选项,如果查找到的选项中flags的值是HAS_ARG,lookup_opt也会将参数字符串赋值给optarg。找到选项和参数之后,QEMU便根据选项中的index枚举值来执行不同的分支。

    对于一些开关性质的选项,分支执行时仅仅是把相关的标志位赋值而已,如:

    3712             case QEMU_OPTION_old_param:
    3713                 old_param = 1;
    3714                 break;
    

    也有一些选项没有子选项,分支执行时就直接把optarg的值交给相关变量:

    3822             case QEMU_OPTION_qtest:
    3823                 qtest_chrdev = optarg;
    3824                 break;
    

    对于那些拥有子选项的选项,如”-drive if=none,id=DRIVE-ID”,QEMU的处理会更为复杂一些。它会调用qemu_opts_parse来解析子选项,如realtime选项的解析:

    3852             case QEMU_OPTION_realtime:
    3853                 opts = qemu_opts_parse(qemu_find_opts("realtime"), optarg, 0);
    3854                 if (!opts) {
    3855                     exit(1);
    3856                 }
    3857                 configure_realtime(opts);
    3858                 break;
    

    对子选项的解析涉及到4个数据结构:QemuOpt, QemuDesc, QemuOpts, QemuOptsList. 它们的关系如下图所示:

    Qemu选项数据结构关系图

    QemuOpt存储子选项,每个QemuOpt有一个QemuOptDesc来描述该子选项名字、类型、及帮助信息。两个结构体定义如下:

     32 struct QemuOpt {
     33     const char   *name;  //子选项的名字
     34     const char   *str;  //字符串值
     35 
     36     const QemuOptDesc *desc;  
     37     union {
     38         bool boolean;  //布尔值
     39         uint64_t uint;  //数字或者大小
     40     } value; 
     41 
     42     QemuOpts     *opts;  
     43     QTAILQ_ENTRY(QemuOpt) next;
     44 };
    
     95 typedef struct QemuOptDesc {
     96     const char *name;
     97     enum QemuOptType type;
     98     const char *help;
     99 } QemuOptDesc;
    

    子选项的类型可以是:

     88 enum QemuOptType {
     89     QEMU_OPT_STRING = 0,   // 字符串
     90     QEMU_OPT_BOOL,       // 取值可以是on或者off
     91     QEMU_OPT_NUMBER,     // 数字
     92     QEMU_OPT_SIZE,       // 大小,可以有K, M, G, T等后缀
     93 };
    

    QEMU维护了一个QemuOptsList*的数组,在util/qemu-config.c中定义:

    10 static QemuOptsList *vm_config_groups[32];
    

    在main函数中由qemu_add_opts将各种QemuOptsList写入到数组中:

    2944     qemu_add_opts(&qemu_drive_opts);
    2945     qemu_add_opts(&qemu_chardev_opts);
    2946     qemu_add_opts(&qemu_device_opts); 
    2947     qemu_add_opts(&qemu_netdev_opts);
    2948     qemu_add_opts(&qemu_net_opts);
    2949     qemu_add_opts(&qemu_rtc_opts);
    2950     qemu_add_opts(&qemu_global_opts);
    2951     qemu_add_opts(&qemu_mon_opts);
    2952     qemu_add_opts(&qemu_trace_opts);
    2953     qemu_add_opts(&qemu_option_rom_opts);
    2954     qemu_add_opts(&qemu_machine_opts);
    2955     qemu_add_opts(&qemu_smp_opts);
    2956     qemu_add_opts(&qemu_boot_opts);
    2957     qemu_add_opts(&qemu_sandbox_opts);
    2958     qemu_add_opts(&qemu_add_fd_opts);
    2959     qemu_add_opts(&qemu_object_opts);
    2960     qemu_add_opts(&qemu_tpmdev_opts);
    2961     qemu_add_opts(&qemu_realtime_opts);
    2962     qemu_add_opts(&qemu_msg_opts);
    

    每个QemuOptsList存储了大选项所支持的所有小选项,如-realtime大选项QemuOptsList的定义:

     507 static QemuOptsList qemu_realtime_opts = {
     508     .name = "realtime",
     509     .head = QTAILQ_HEAD_INITIALIZER(qemu_realtime_opts.head),
     510     .desc = {
     511         {
     512             .name = "mlock",
     513             .type = QEMU_OPT_BOOL,
     514         },
     515         { /* end of list */ }
     516     },
     517 };
    

    -realtime只支持1个子选项,且值为bool类型,即只能是on或者off。

    在调用qemu_opts_parse解析子选项之前,QEMU会调用qemu_find_opts(“realtime”),把QemuOptsList *从qemu_add_opts中找出来,和optarg一起传递给qemu_opts_parse去解析。QEMU可能会多次使用同一个大选项来指定多个相同的设备,在这种情况下,需要用id来区分。QemuOpts结构体就表示同一id下所有的子选项,定义如下:

     46 struct QemuOpts {
     47     char *id;
     48     QemuOptsList *list;
     49     Location loc;
     50     QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
     51     QTAILQ_ENTRY(QemuOpts) next;
     52 };
    

    其中list是同一个大选项下不同id的QemuOpts链表。


    展开全文
  • QEMU 的 UEFI BIOS 建造 准备 git clone https://github.com/tianocore/edk2.git cd edk2 bios32.bin OvmfPkg/build.sh -a IA32 -n 4 cp Build/OvmfX64/DEBUG_GCC4?/FV/OVMF.fd bios32.bin bios64.bin OvmfPkg/...
  • cento7安装kvm并通过qemu命令行安装其他虚拟机(红帽) 1.材料准备(蓝字可点击下载) 链接: centos7 提取码:3h2k 链接: RedHat 提取码:12jm 链接: qemu 提取码:kz9b 2.开始 1)打开centos,检查是否支持虚拟...
  • QEMU安装包.zip

    2020-03-06 17:44:28
    资源为QEMU安装包,在压缩包内带有安装方法,亲测在Ubuntu16.04下正常安装,有需要的朋友可以下载。
  • 通过QEMU / HVF进行macOS操作 在具有Hypervisor的基于Intel的Mac主机上通过QEMU运行macOS的示例。框架加速( -accel hvf ) 一些必需的东西 (尚未将修补程序合并到qemu master中) -AppleSMC仿真必需 macOS安装...
  • qemu-android-x86-runner:如何在QEMU中运行Android x86的快速入门
  • QEMU 支持使用 RustSBI编译并运行:cargo qemu当运行cargo qemu ,测试内核将构建并运行。预期输出应该是:xtask: mode: Debug Compiling rustsbi-qemu v0.1.0 (D:\RustProjects\rustsbi-qemu\rustsbi-qemu) ...
  • 20200619-QEMU BIOS简介.pptx
  • qemu_imx6ull_windows.zip

    2020-05-05 21:46:58
    为何要在Windows搭建QEMU? 由于使用的是虚拟机运行Linux, 然后再Linux上运行QEMU模拟开发板, 即使使用KVM加速也达不到加速的效果(KVM是基于硬件的完全虚拟化), 所以产生了不必要的性能损耗导致在虚拟机上的QEMU运行...
  • qemu-5.1.0.tar.xz

    2020-08-17 13:36:05
    qemu5.1版本源码,开源,开源作虚拟机或者仿真开发板。 QEMU 5.0 Supports Recent Armv8.x Features, Cortex-M7 CPU, Host Directory Access, and More
  • qemu-rpi内核 使用Qemu的本机raspi2 / 3机器进行仿真 请遵循native-emulation子文件夹下的说明,以使用Qemu的本机raspi2 / 3机器来仿真树莓派。 使用预编译的通用pb内核进行仿真 现成的内核,可用于使用QEMU模仿...
  • Limbo是一个类似于qemu-user的XNU仿真器。 它将XNU系统调用转换为它们Linux等效项。 它能够在Linux上执行针对macOS或iOS的受支持的二进制文件,而无需进行修改。 limbo Limbo是一个类似于qemu-user的XNU模拟器。 它...
  • Go-qemu go-qemu是Go软件包的集合,用于与正在运行的QEMU实例进行交互。 Apache 2.0许可。 如果您想讨论该项目, 随时加入我们在 。 安装 使用go get检索go-qemu所有软件包: $ go get github....
  • xPack QEMU ARM分支 基本原理 该存储库是官方存储库的分支,并且创建该存储库是为了存储在中执行的更改。 网址 https://github.com/xpack-dev-tools/qemu.git该fork的URL git://git.qemu.org/qemu.git上游Git的URL...
  • qemu-w64-setup-20201124.exe QEMU Windows 64位2020年最新版黑苹果专用虚拟机工具
  • qemu-5.2.0.tar.xz

    2021-01-02 22:41:31
    虚拟机软件:qemu 5.2.0
  • Qemu Debian mipsel/mips64el

    2020-07-18 22:40:56
    Vmware Ubuntu虚拟机,内置Qemu,已安装Debian7 mipsel和Debian10 mips64el 已配置好桥接网络,运行qemu-Debian可直接访问网络 安装及配置教程如下https://blog.csdn.net/u012501842/article/details/107425586
  • 静态编译Qemu 版本4.2.0 目标平台aarch64/arm64/armv8 只编译了qemu-system-x86_64和qemu-x86_64(user) 解压后用安卓终端运行 可执行文件目录./bin
  • Ubuntu18.04+Qemu调试Linux内核实验记录 实验环境 操作系统:Ubuntu18.04 依赖项安装: sudo apt-get install texinfo sudo apt-get install libncurses5-dev sudo apt-get install m4 sudo apt-get install flex ...
  • 用于 Ubuntu 20根文件的 qemu-arm-static

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 55,884
精华内容 22,353
关键字:

qemu