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功能开发记录(三),数据收发基于寄存器级别解释 💖 作者简介:大家好,我是喜欢记录零碎知识点的小菜鸟。😎📝 个人主页…...
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:作…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
