QEMU源码全解析17 —— QOM介绍(6)

接前一篇文章:QEMU源码全解析16 —— QOM介绍(5)

本文内容参考:

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

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

特此致谢!

上一回讲解了QOM的第二部分 —— 类型的初始化,重点分析了type_initialize函数。类的初始化是通过type_initialize函数完成的。下边以其中一条路径来看type_initialize函数的调用过程。

通过上一回的type_initialize函数代码可以知道,其是static的,也就是说仅在qom/object.c文件内有效。这就好办多了,直接在文件中搜索type_initialize关键字就好了。一共有以下几处调用:

(1)type_initialize() -> type_initialize()

这就是上一回讲的递归初始化所有父类型。

(2)object_initialize_with_type() -> type_initialize()

(3)object_new_with_type() -> type_initialize()

(4)object_class_by_name() -> type_initialize()

(5)object_class_get_parent() -> type_initialize()

(6)object_class_foreach_tramp() -> type_initialize()

(7)type_initialize_interface() -> type_initialize()

下边以其中一条路径来看type_initialize的调用过程。

QEMU会在qemu_init函数中调用qemu_create_machine函数。代码如下:

qemu_create_machine(machine_opts_dict);

qemu_create_machine函数在同文件(softmmu/vl.c)中,代码如下:

static void qemu_create_machine(QDict *qdict)
{MachineClass *machine_class = select_machine(qdict, &error_fatal);object_set_machine_compat_props(machine_class->compat_props);current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));object_property_add_child(object_get_root(), "machine",OBJECT(current_machine));object_property_add_child(container_get(OBJECT(current_machine),"/unattached"),"sysbus", OBJECT(sysbus_get_default()));if (machine_class->minimum_page_bits) {if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) {/* This would be a board error: specifying a minimum smaller than* a target's compile-time fixed setting.*/g_assert_not_reached();}}cpu_exec_init_all();page_size_init();if (machine_class->hw_version) {qemu_set_hw_version(machine_class->hw_version);}/** Get the default machine options from the machine if it is not already* specified either by the configuration file or by the command line.*/if (machine_class->default_machine_opts) {QDict *default_opts =keyval_parse(machine_class->default_machine_opts, NULL, NULL,&error_abort);qemu_apply_legacy_machine_options(default_opts);object_set_properties_from_keyval(OBJECT(current_machine), default_opts,false, &error_abort);qobject_unref(default_opts);}
}

函数一开始调用了select_machine函数,该函数仍然在同文件中,代码如下:

static MachineClass *select_machine(QDict *qdict, Error **errp)
{const char *optarg = qdict_get_try_str(qdict, "type");GSList *machines = object_class_get_list(TYPE_MACHINE, false);MachineClass *machine_class;Error *local_err = NULL;if (optarg) {machine_class = find_machine(optarg, machines);qdict_del(qdict, "type");if (!machine_class) {error_setg(&local_err, "unsupported machine type");}} else {machine_class = find_default_machine(machines);if (!machine_class) {error_setg(&local_err, "No machine specified, and there is no default");}}g_slist_free(machines);if (local_err) {error_append_hint(&local_err, "Use -machine help to list supported machines\n");error_propagate(errp, local_err);}return machine_class;
}

进而由select_machine函数中的find_default_machine函数来找默认的machine类型。fine_default_machine函数也是在softmmu/vl.c中,代码如下:

static MachineClass *find_default_machine(GSList *machines)
{GSList *el;MachineClass *default_machineclass = NULL;for (el = machines; el; el = el->next) {MachineClass *mc = el->data;if (mc->is_default) {assert(default_machineclass == NULL && "Multiple default machines");default_machineclass = mc;}}return default_machineclass;
}

回到上一级select_machine函数中。该函数中有这样一行代码:

GSList *machines = object_class_get_list(TYPE_MACHINE, false);

select_machine函数调用object_class_get_list函数以得到所有TYPE_MACHINE类型组成的链表。

oject_class_get_list函数在qom/object.c中,代码如下:

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;
}

object_class_foreach函数在同文件中,代码如下:

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;
}

可以看到,object_class_foreach函数会对type_table中所有类型调用object_class_foreach_tramp函数,即最终会对类型哈希表type_table中的每一个元素调用object_class_foreach_tramp函数。

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函数中会调用type_initialize函数。这样,在执行select_machine函数的时候就顺带把所有类型都初始化了。

至此,QOM的第二部分 —— 类型的初始化就介绍完了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/11739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【通讯录】--C语言

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

路由策略(重发布)

要求&#xff1a; 1、使用双点双向重发布 2、所有路由器进行最佳选路 3、存在备份路径&#xff0c;不得出现环路&#xff0c;和路由回馈 1.更改设备名称配置接口IP地址 R1 <Huawei>system-view [Huawei]sysname R1 [R1]interface GigabitEthernet 0/0/0 [R1-GigabitEt…

Linux和Mac环境下的Nginx安装教程

Linux安装 登录root账号&#xff0c;服务器环境为阿里云的Cent OS 7.6版本 执行yum install yum-utils 运行vim /etc/yum.repos.d/nginx.repo 输入&#xff1a; [nginx-stable]namenginx stable repobaseurlhttp://nginx.org/packages/centos/7/$basearch/gpgcheck1enable…

ChatGPT在语义理解和信息提取中的应用如何?

ChatGPT在语义理解和信息提取领域有着广泛的应用潜力。语义理解是指对文本进行深层次的理解&#xff0c;包括词义、句义和篇章义等层面的理解。信息提取是指从文本中自动抽取结构化的信息&#xff0c;如实体、关系、事件等。ChatGPT作为一种预训练语言模型&#xff0c;具有丰富…

Python深度学习“四大名著”之一【赠书活动|第二期《Python机器学习:基于PyTorch和Scikit-Learn》】

近年来&#xff0c;机器学习方法凭借其理解海量数据和自主决策的能力&#xff0c;已在医疗保健、 机器人、生物学、物理学、大众消费和互联网服务等行业得到了广泛的应用。自从AlexNet模型在2012年ImageNet大赛被提出以来&#xff0c;机器学习和深度学习迅猛发展&#xff0c;取…

MATLAB与ROS联合仿真(慕羽☆)全套开源资料索引

自2021年9月份开始进行MATLAB与ROS联合仿真相关的研究&#xff0c;至2021年12月份研究基本上结束&#xff0c;至今&#xff0c;已经近两年时间&#xff0c;期间曾收到过很多小伙伴的私信&#xff0c;想让我出点教程&#xff0c;期间我也曾多次想要抽点时间出教程&#xff0c;但…

112、SpringBoot中配置文件的加载顺序是怎样的?

SpringBoot中配置文件的加载顺序是怎样的&#xff1f; 优先级从高到低&#xff0c;高优先级的配置覆盖低优先级的配置&#xff0c;所有配置会形成互补配置。 命令行参数。所有的配置都可以在命令行上进行指定Java系统属性(System.getProperties());操作系统环境变量;jar包外部…

JMeter 怎么查看 TPS 数据教程,简单易懂

TPS 是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时&#xff0c;收到服务器响应后结束计时&#xff0c;以此来计算使用的时间和完成的事务个数。在 JMeter 中&#xff0c;我们可以使用以下方法查看 T…

华为战略方法论:BLM模型之关键任务与依赖关系

内容简介 在 BLM 模型中&#xff0c;执行部分包括四个模块&#xff0c;分别是&#xff1a; 关键任务与依赖关系&#xff1b;组织与绩效&#xff1b;人才&#xff1b;氛围与文化。 详细内容&#xff0c;大家可以参看下面这张图。 这四个模块其实是可以进一步划分成两个关键点…

MFC自定义控件使用

用VS2005新建一个MFC项目,添加一个Custom Control控件在窗体 我们需要为自定义控件添加一个类。项目,添加类,MFC类 设置类名字,基类为CWnd,你也可以选择CDialog作为基类 类创建完成后,在它的构造函数中注册一个新的自定义窗体,取名为"MyWindowClass" WNDCL…

8.11 PowerBI系列之DAX函数专题-TopN中实现N的动态

需求 实现 1 ranking by amount rankx(allselected(order_2[产品名称]),[total amount]) 2 rowshowing_boolean var v_ranking [ranking by amount] var v_topN-no [topN参数 值] var v_result int( v_ranking < v_topN_no) return v_result 3 将度量值2放入视觉对象筛…

大数据Flink(五十二):Flink中的批和流以及性能比较

文章目录 Flink中的批和流以及性能比较 ​​​​​​​​​​​​​​一、Flink中的批和流

【网络云盘客户端】——上传文件的功能的实现

目录 上传文件功能的实现 uploadtask的设计 设置上传的槽函数 uploadFileAction接口 uploadFile接口 定时上传文件 进度条的设计 上传文件功能的实现 上传文件功能实现 1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框 2.在文…

华为云安装MySQL后,本地工具连接MySQL失败

华为云安装MySQL后&#xff0c;本地连接失败 排查问题步骤&#xff1a; 在此之前需要在MySQL创建用户&#xff0c;并赋予权限。 1、能否ping通。 在本地命令行(Windows&#xff1a;winR)通过ping命令&#xff0c;ping服务器地址&#xff0c;看能否ping通。不能则需要检查本地…

【C++入门】浅谈类、对象和 this 指针

文章目录 一、前言二、类1. 基本概念2. 类的封装3. 使用习惯成员函数定义习惯成员变量命名习惯 三、对象1. 基本概念2. 类对象的存储规则 四、this 指针1. 基本概念2. 注意事项3. 经典习题4. 常见面试题 一、前言 在 C 语言中&#xff0c;我们用结构体来描述一个事物的多种属性…

ubuntu docker离线安装docker(.deb包方式)(成功)(附卸载方法)

参考文章&#xff1a;Install Docker Engine on Ubuntu 文章目录 安装步骤下载安装包拷贝到目标主机并执行安装命令 验证拉取运行容器测试build dockerfile测试持久运行容器测试主机重启后&#xff0c;docker各服务是否正常自启 卸载方法附&#xff1a;各安装包作用说明&#x…

C++的类型转换运算符:static_cast

C的类型转换运算符&#xff1a;static_cast static_cast 用于在相关类型的指针之间进行转换&#xff0c;还可显式地执行标准数据类型的类型转换—这种转换原本将自动或隐式地进行。用于指针时&#xff0c; static_cast 实现了基本的编译阶段检查&#xff0c;确保指针被转换为相…

express编写一个简单的get接口

/01编写get接口.jsconst express require(express) const app express()// 创建路由 const useRouter require(./router/user.js) // 注册路由 app.use(/api,useRouter)app.listen(8080, (req, res) > {console.log(8080监听) }) ./02编写post接口 // 注意&#xff1a;如…

mac cli文件管理器

背景 最近研究了一下在控制台查看文件的插件ranger, 官方的解释是&#xff1a;一个cli下的文件管理器。觉得效果也很酷炫&#xff0c;所以在此展示一下。 安装 brew install ranger配置生成 建议第一次使用的时候使用 ranger --copy-configall将会在~/.config/ranger目录输…

VScode 避免逗号、括号时自动补全

设置项 控制是否应在遇到提交字符时接受建议。例如&#xff0c;在JavaScript中&#xff0c;半角分号(;)可以为提交字符&#xff0c;能够在接受建议的同时键入该字符。 "editor.acceptSuggestionOnCommitCharacter": false起因 比如打伪代码的时候输入一些缺少上下…