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:作…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...
麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
