当前位置: 首页 > news >正文

QEMU源码全解析35 —— Machine(5)

接前一篇文章:QEMU源码全解析34 —— Machine(4)

本文内容参考:

《趣谈Linux操作系统》 —— 刘超,极客时间

《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社

特此致谢!

上回书说到有3个函数需要弄清楚:(1)object_class_get_list_tramp;(2)object_foreach_tramp;(3)type_table_get。本回对于这3个函数进行解析。

为了便于理解,再次贴出qom/object.c中的object_class_get_list函数以及其调用的同文件中的object_class_foreach函数,代码分别如下:

GSList *object_class_get_list(const char *implements_type,bool include_abstract)
{GSList *list = NULL;object_class_foreach(object_class_get_list_tramp,implements_type, include_abstract, &list);return list;
}
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),const char *implements_type, bool include_abstract,void *opaque)
{OCFData data = { fn, implements_type, include_abstract, opaque };enumerating_types = true;g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);enumerating_types = false;
}

先来看第1个函数type_table_get,也在qom/object.c中,代码如下:

static GHashTable *type_table_get(void)
{static GHashTable *type_table;if (type_table == NULL) {type_table = g_hash_table_new(g_str_hash, g_str_equal);}return type_table;
}

在全局表type_table_get()即返回的type_table中,对于每一项TypeImpl,都执行object_class_foreach_tramp。

再来看第2个函数object_class_foreach_tramp,从名字上就能看出来,它也是在qom/object.c中。代码如下:

static void object_class_foreach_tramp(gpointer key, gpointer value,gpointer opaque)
{OCFData *data = opaque;TypeImpl *type = value;ObjectClass *k;type_initialize(type);k = type->class;if (!data->include_abstract && type->abstract) {return;}if (data->implements_type && !object_class_dynamic_cast(k, data->implements_type)) {return;}data->fn(k, data->opaque);
}

object_class_foreach_tramp函数的参数OCFData *data实际指向了object_class_foreach函数中的data,即OCFData data = { fn, implements_type, include_abstract, opaque }。代入上下文的实际值GSList *machines = object_class_get_list(TYPE_MACHINE, false),最终是:OCFData data = { fn, TYPE_MACHINE, false, &list }。

我们在前文书讲QOM的时候详细解析过type_initialize函数,其作用是类的初始化,这里当然是对TYPE_MACHINE即"machine"类的初始化。type_initialize函数中会调用class_init函数将纸面上的class即TypeImpl转变为ObjectClass。前文书也提到过,ObjectClass是所有Class类的祖先,而这里的MachineClass是其子类。

函数最后的data->fn(k, data->opaque)代入实际值为object_class_get_list_tramp(type->class, &list)。

最后看第3个函数object_class_get_list_tramp,其也在qom/object.c中,代码如下:

static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
{GSList **list = opaque;*list = g_slist_prepend(*list, klass);
}

在命令行中传入"-machine xx-xxx-xxx"也好,不指定相关值而使用默认值也罢,最终都能够找到之前已注册过的TypeImpl,并调用它的class_init函数。因而pc_machine_##suffix##class_init即“.class_init = pc_machine_v7_1_class_init”会被调用。再次给出相关代码,如下:

static void pc_init_v7_1(MachineState *machine)
{void (*compat)(MachineState *m) = (NULL);if (compat) {compat(machine);}pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, \TYPE_I440FX_PCI_DEVICE);
}static void pc_machine_v7_1_class_init(ObjectClass *oc, void *data)
{MachineClass *mc = MACHINE_CLASS(oc);pc_i440fx_7_1_machine_options(mc);mc->init = pc_init_v7_1;
}
static const TypeInfo pc_machine_type_v7_1 = {.name       = "pc-i440fx-7.1" TYPE_MACHINE_SUFFIX,.parent     = TYPE_PC_MACHINE,.class_init = pc_machine_v7_1_class_init,
};
static void pc_machine_init_v7_1(void)
{type_register(&pc_machine_type_v7_1);
}

在pc_machine_##suffix##class_init即pc_machine_v7_1_class_init函数中,pc_i440fx_7_1_machine_options函数才真正被调用以初始化MachineClass,并将MachineClass的init函数设置为pc_init##suffix即pc_init_v7_1。也即,当select_machine执行完毕后,就有一个MachineClass了。

pc_i440fx_7_1_machine_options函数在hw/i386/pc_piix.c中,代码如下:

static void pc_i440fx_7_1_machine_options(MachineClass *m)
{PCMachineClass *pcmc = PC_MACHINE_CLASS(m);pc_i440fx_machine_options(m);m->alias = "pc";m->is_default = true;pcmc->default_cpu_version = 1;pcmc->legacy_no_rng_seed = true;
}

pc_i440fx_machine_options函数就在上边,代码如下:

static void pc_i440fx_machine_options(MachineClass *m)
{PCMachineClass *pcmc = PC_MACHINE_CLASS(m);pcmc->default_nic_model = "e1000";pcmc->pci_root_uid = 0;m->family = "pc_piix";m->desc = "Standard PC (i440FX + PIIX, 1996)";m->default_machine_opts = "firmware=bios-256k.bin";m->default_display = "std";machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
}

本回内容较多,需要认真结合前文反复理解,也算作一个对前文的复习回顾。介绍完了这3个函数后,回到select_machine函数中,继续往下进行解析。详情请看下文。

相关文章:

QEMU源码全解析35 —— Machine(5)

接前一篇文章:QEMU源码全解析34 —— Machine(4) 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社 特此致谢! 上回书说到有3…...

SpringBoot对一个URL通过method(GET、POST、PUT、DELETE)实现增删改查操作

目录 1. rest风格基础2. 开启方法3. 实战练习 1. rest风格基础 我们都知道GET、POST、PUT、DELETE分别对应查、增、改、删除 虽然Postman这些工具可以直接发送GET、POST、PUT、DELETE请求。但是RequestMapping并不支持PUT和DELETE请求操作。需要我们手动开启 2. 开启方法 P…...

webpack 创建VUE项目

1、安装 node.js 下载地址:https://nodejs.org/en/ 下载完成以后点击安装,全部下一步即可 安装完成,输入命令验证 node -vnpm -v2.搭建VUE环境 输入命令,全局安装 npm install vue-cli -g安装完成后输入命令 查看 vue --ver…...

deepin 深度操作系统正式适配苹果 M1 芯片

导读近日消息,据深度操作系统官方消息,在已经发布的 deepin V23 beta 版本中,深度操作系统正式适配 Apple Mac mini M1 了。 官方表示,Mac mini M1 是苹果于 2020 年 11 月发布的迷你电脑主机,它搭载了最高 3.2GHz …...

Labview控制APx(Audio Precision)进行测试测量(七)

处理集群控制子集 大多数用户不会想要设置所有的控制包括在一个大的控制集群,如水平和增益配置控制。例如,假设您只在 APx 中使用模拟不平衡输出连接器,而您想要做的就是控制发电机的电平和频率。在这种情况下,水平和增益配置集群…...

Mybatis 源码 ② :流程分析

文章目录 一、前言二、Mybatis 初始化1. AutoConfiguredMapperScannerRegistrar2. MapperScannerConfigurer3. ClassPathMapperScanner3.1 ClassPathMapperScanner#scan3.2 ClassPathMapperScanner#processBeanDefinitions 4. 总结 三、 Mapper Interface 的创建1. MapperFacto…...

Unity2D RPG开发笔记 P1 - Unity界面基础操作和知识

文章目录 工具选择简单快捷键Game 窗口分辨率检视器Transform 组件Sprite Renderer综合检视器 工具选择 按下 QWERTY 可以选择不同的工具进行 旋转、定位、缩放 简单快捷键 按下 Ctrl D 可以复制物体 Game 窗口分辨率 16:9 为最常见的分辨率 检视器 Transform 组件 物体在…...

聚类与回归

聚类 聚类属于非监督式学习(无监督学习),往往不知道因变量。 通过观察学习,将数据分割成多个簇。 回归 回归属于监督式学习(有监督学习),知道因变量。 通过有标签样本的学习分类器 聚类和…...

了解IL汇编循环

IL代码, .assembly extern mscorlib {}.assembly Test{.ver 1:0:1:0}.module test.exe.method static void main() cil managed{.maxstack 8.entrypoint.locals init (int32, int32)ldc.i4 4stloc.0 //Upper limit of the Loop, total 5 ldc.i4 0 stloc.…...

电脑突然黑屏的解决办法

记录一次电脑使用问题 问题描述 基本情况:雷神游戏笔记本 windows10操作系统 64位 使用时间 4年 日期:2023年8月11日 当时 电脑充着电 打开了两个浏览器:edge[页面加载5个左右],火狐[页面加载1个左右] 两个文件夹 一个百度网盘…...

socket练习

socket练习 工具目的代码运行结果 工具 pycharm 目的 使用socket进行图片采集 代码 采集流程: 1 获取url 2 发送请求,获取数据 3 提取数据 4 保存数据 import socket import reurls [https://pic.netbian.com/uploads/allimg/220211/004115-1644511…...

Gitlab CI/CD笔记-第二天-主机套接字进行构建并push镜像。

一、安装gitlab-runner 1.可以是linux也可以是docker的 2.本文说的是docker安装部署的。 二、直接上.gitlab-ci.yml stages: # List of stages for jobs, and their order of execution - build-image build-image-job: stage: build-image image: harbor.com:543/docke…...

nginx服务器报错502 Bad Gateway的原因以及解决办法

服务器报错nginx 502 Bad Gateway的原因以及解决办法_502 bad gateway nginx_主题模板站的博客-CSDN博客...

带你了解什么是内容协商---如何返回不同媒体类型的数据

😀前言 本篇博文是关于客户端接收能力不同,SpringBoot 返回不同媒体类型的数据如何处理的说明,希望你能够喜欢😊 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀&#…...

容器化相关面试题

Docker相关面试题 (1)Docker的组件包含哪些? 客户端:dockerclient服务端:dockerserver## 能看到相关的信息 docker info## docker client向docker daemon发送请求,docker daemon完成相应的任务,并把结果返还给容器 Docker镜像: docker镜像是一个只读的模板,是启动一…...

BIO、NIO、AIO 有什么区别

在Java中,BIO(Blocking I/O)、NIO(Non-blocking I/O)和AIO(Asynchronous I/O)都是用于处理I/O(输入/输出)操作的不同方式。它们在处理I/O时具有不同的特点和适用场景。 B…...

如何构建一个对象池并使用

1.背景 在项目中,如果频繁的通过new 创建对象,之后让gc再去回收,这就很容易造成内存抖动,并且频繁的GC本身也会消耗内存,这样就很容易在一瞬间造成OOM 内存溢出,因为瞬间申请大量内存会造成内存占用突然升…...

【沁恒蓝牙mesh】CH58x USB功能开发记录(三)

本博文主要记录 ,【沁恒蓝牙mesh】CH58x USB功能开发记录(三),数据收发基于寄存器级别解释 💖 作者简介:大家好,我是喜欢记录零碎知识点的小菜鸟。😎📝 个人主页&#xf…...

2023国赛数学建模D题思路分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…...

linux 学习————LNMP之分布式部署

目录 一、概述 二、LNMP环境部署 三、配置nginx 四、 配置php使nginx能够解析.php 五、配置mysql 六、配置discuz进行登录论坛访问测试 一、概述 LNMP代表 Linux、Nginx、MySQL、PHP,是一种常用的服务器架构。它由以下组件组成: Linux:作…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

Vue ③-生命周期 || 脚手架

生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)

名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor

1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...

电脑桌面太单调,用Python写一个桌面小宠物应用。

下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...