qemu虚拟化-qom框架(qom进阶之设备初始化)

接上一篇文章中介绍的qom的基本用法和qom面向对象实现原理,这一篇讲一下qom实现的源码

1.初始化函数的注册

类型注册的调用接口是type_init(xxx_register_types)type_init是个宏定义,最终原理是gcc 的constructor属性,添加这个属性描述的函数为初始化函数,会在main函数执行之前执行,最后宏定义的作用就是在xxx_register_types 之前加上一个__attribute__((constructor)),再改改名字。目的是在main函数之前就注册好类型。

2.类的注册

xxx_register_types逻辑里面通常是注册类调用的函数是type_register_static(&xxx_info);,我们追踪一下这个函数的实现,源码主要在qom/object.c中:

->type_register_static
	->type_register
		->type_register_internal
			->type_new
			->type_table_add
				->g_hash_table_insert

g_hash_table_insert暂时不深究,认为是一个hash_table容器即可。现在我们的类就注册好了。下面看一下类的初始化逻辑。

3.sysbus的初始化

sysbus的初始化的初始化源自vl.c main函数里面的 qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
开始初始化最初的sysbus总线,这个是qemu默认有的总线,可以类比linux内核的platform总线。之后开始一系列sysbus的初始化,下面看一下过程
sysbus.c

->sysbus_get_default
	->main_system_bus_create
		->qbus_create_inplace

bus.c

		->qbus_create_inplace
			->object_initialize

objetc.c

->object_initialize
	->object_initialize_with_type
		->type_initialize
			->ti->class_init(ti->class, ti->class_data);
		->object_init_with_type
			->ti->instance_init(obj);
3.设备的初始化

设备的初始化源自vl.c main中的 qemu_opts_foreach(qemu_find_opts("device"),device_init_func, NULL, &error_fatal);,根据命令行参数来做初始化,具体命令解析不细说,感兴趣的自行分析。下面看一下设备初始化流程
vl.c

->device_init_func
	->qdev_device_add

qdev-monitor.c

->qdev_device_add
	->qemu_opt_get
	->qdev_get_device_class
		->object_class_by_name
	->dev = DEVICE(object_new(driver));
		->object_new
	->object_property_set_bool(OBJECT(dev), true, "realized", &err);

object_class_by_name主要是获取一些信息,object_new是真正的设备初始化,逻辑就是对object_initialize_with_type的封装,上面已经介绍过object_initialize_with_type了,下面还是看一下细节:
objetc.c

->object_new
	->object_initialize_with_type
		->type_initialize
			->ti->class_init(ti->class, ti->class_data);
		->object_init_with_type
			->ti->instance_init(obj);

大多数设备有注册realize函数,这个函数是在什么时候触发点呢?秘密就在object_property_set_bool(OBJECT(dev), true, "realized", &err);,这个函数有点绕,来看一下具体过程

首先是注册过程,设备的realized属性在对象初始化的时候注册,逻辑在父类qdev中,来看一下:

static const TypeInfo device_type_info = {
    .name = TYPE_DEVICE,
    .parent = TYPE_OBJECT,
    .instance_size = sizeof(DeviceState),
    .instance_init = device_initfn,
    .instance_post_init = device_post_init,
    .instance_finalize = device_finalize,
    .class_base_init = device_class_base_init,
    .class_init = device_class_init,
    .abstract = true,
    .class_size = sizeof(DeviceClass),
};

关注device_initfn函数的逻辑
qdev.c

->device_initfn
	->object_property_add_bool(obj, "realized", device_get_realized, device_set_realized, NULL);
		->device_get_realized
			->return dev->realized;
		->device_set_realized
			->dc->realize(dev, &local_err);

看到在设置设备对象的realized属性且参数为true的时候会调用设备的realize函数。这就对应上了上面的属性设置。到这里从命令行参数到设备初始化就讲完了

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值