博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
qemu-qdev
阅读量:4095 次
发布时间:2019-05-25

本文共 13436 字,大约阅读时间需要 44 分钟。

qemu中创建设备的接口为qdev_new函数。DeviceState *qdev_new(const char *name){
if (!object_class_by_name(name)) {
module_load_qom_one(name); } return DEVICE(object_new(name));}当创建设备时,qemu首先根据名字找到其所对应的对象类,随后再根据名字创建所需的设备对象。在qemu中,采用了面对对象的设计模式,因此,存在ObjectClass与Object两个结构体,前者用来声明一个类,而后者则用来声明一个实例对象。而在面向对象的设计模式中,实例对象的创建都是通过类来完成,因此,在qemu中一个Object的对象,必须要确定其所对应的ObjectClass存在。来看一下ObjectClass和Object结构体的定义。struct ObjectClass{
Type type; GSList *interfaces; const char *object_cast_cache[OBJECT_CLASS_CAST_CACHE]; const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE]; //class_cast_cache用来寄存当前基类所相关的子类 ObjectUnparent *unparent; GHashTable *properties;};struct Object{
ObjectClass *class; ObjectFree *free; GHashTable *properties; uint32_t ref; Object *parent;};继续对object_class_by_name函数进行分析。ObjectClass *object_class_by_name(const char *typename){
TypeImpl *type = type_get_by_name(typename); if (!type) {
return NULL; } type_initialize(type); return type->class;}static TypeImpl *type_get_by_name(const char *name){
if (name == NULL) {
return NULL; } return type_table_lookup(name);}static TypeImpl *type_table_lookup(const char *name){
return g_hash_table_lookup(type_table_get(), name);}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;}通过上边的代码可知,qemu通过哈希表找到与设备名称相对应的struct TypeImpl结构体对象,并接着执行type_initialize函数来初始化该结构体,其中OjectClass则是该结构体所指向的class对象。static void type_initialize(TypeImpl *ti){
TypeImpl *parent; if (ti->class) {
return; } ti->class_size = type_class_get_size(ti); //获取TypeImpl对象所属的类的大小,如果有赋值则直接返回,如果没有但是存在父类,则返回父类的大小,否则返回ObjectClass结构体的大小。 ti->instance_size = type_object_get_size(ti); if (ti->instance_size == 0) {
ti->abstract = true; } if (type_is_ancestor(ti, type_interface)) {
assert(ti->instance_size == 0); assert(ti->abstract); assert(!ti->instance_init); assert(!ti->instance_post_init); assert(!ti->instance_finalize); assert(!ti->num_interfaces); } ti->class = g_malloc0(ti->class_size); //创建TypeImpl所对应的ObjectClass结构体对象 parent = type_get_parent(ti); //获取父类 if (parent) {
//如果父类存在 type_initialize(parent); GSlist *e; int i; g_assert(parent->class_size <= ti->class_size); g_assert(parent->instance_size <= ti->instance_size); memcpy(ti->class, parent->class, parent->class_size); //将父类中的类属性拷贝到子类当中 ti->class->interfaces = NULL; for (e = parent->calss->interfaces; e; e = e->next) {
InterfaceClass *iface = e->data; ObjectClass *klass = OBJECT_CLASS(iface); type_initialize_interface(ti, iface->interface_type, klass->type); } for (i = 0; i < ti->num_interfaces; i++) {
TypeImpl *t = type_get_by_name(ti->interfaces[i].typename); if (!t) {
error_report("missing interface '%s' for object '%s'", ti->interfaces[i].typename, parent->name); abort(); } for (e = ti->class->interfaces; e; e = e->next) {
TypeImpl *target_type = OBJECT_CLASS(e->data)->type; if (type_is_ancestor(target_type, t)) {
break; } } if (e) {
continue; } type_initialize_interface(ti, t, t); } //初始接口 } ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, object_property_free); //创建当前类的属性链表,即哈希链表 ti->class->type = ti; while (parent) {
if (parent->class_base_init) {
parent->class_base_init(ti->class, ti->class_data); } parent = type_get_parent(parent); } if (ti->class_init) {
ti->class_init(ti->class, ti->class_data); } //执行TypeImpl结构体所指向的class_init函数,即类的初始化函数}对上边代码中的type_class_get_size和type_get_parent函数进行分析,如下:static size_t type_class_get_size(TypeImpl *ti){
if (ti->class_size) {
return ti->class_size; } if (type_has_parent(ti)) {
return type_class_get_size(type_get_parent(ti)); } return sizeof(ObjectClass);}static TypeImpl *type_get_parent(TypeImpl *type){
if (!type->parent_type && type->parent type->parent_type = type_get_by_name(type->parent); if (!type->parent_type) {
fprintf(stderr, "Type '%s' is missing its parent '%s'\n", type->name, type->parent); abort(); //立即结束,不做任何操作 } } return type->parent_type;}当根据名字可以查找到所对应的ObjectClass之后,便可以创建实例对象了,即object_new(name)。Object *object_new(const char *typename){
TypeImpl *ti = type_get_by_name(typename); return object_new_with_type(ti);}Object *object_new_with_type(Type type){
Object *obj; g_assert(type != NULL) type_initialize(type); obj = g_malloc(type->instance_size); //申请实例对象所需的空间大小 object_initialize_with_type(obj, type->instance_size, type); //初始实例化对象 obj->free = g_free; return obj;}关于object_new_with_type函数中的参数类型,原型为:typedef struct TypeImpl *Type;static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type){
type_initialize(type); g_assert(type->instance_size >= sizeof(Object)); g_assert(type->abstract == false); g_assert(size >= type->instance_size); memset(obj, 0, type->instance_size); obj->class = type->class; object_ref(obj); object_class_property_init_all(obj); obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, object_property_free); object_init_with_type(obj, type); //object_init_with_type函数会执行实例化的初始化 object_post_init_with_type(obj, type);}当初始完一个示例对象之后,需要根据实际的实例对象在进行封装,通常会通过不同的宏来完成,比如:设备对象示例——DEVICE。当设备创建完成后,便可以通过函数qdev_realize或者qdev_realize_and_unref函数来实现设备,后者会通过调用前者来完成。bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp){
assert(!dev->realized && !dev->parents_bus); if (bus) {
qdev_set_parent_bus(dev, bus); } else {
assert(!DEVICE_GET_CLASS(dev)->bus_type); } return object_property_set_bool(OBJECT(dev), "realized", true, errp);}关于设置object对象属性的object_property_set_bool函数,首先了解如下的结构体:struct QBool {
struct QObjectBase_ base; bool value;};struct QObject {
struct QObjectBase_ base;};struct QObjectBase_ {
QType type; size_t refcnt;};typedef enum QType {
QTYPE_NONE; QTYPE_QNULL, QTYPE_QNUM, QTYPE_QSTRING, QTYPE_QDICT, QTYPE_QLIST, QTYPE_QBOOL, QTYPE__MAX,} QType;bool object_property_set_bool(Object *obj, const char *name, bool value, Error **errp){
QBool *qbool = qbool_from_bool(value); //创建QBool结构体对象,并进行初始化 bool ok = object_peoperty_set_qobject(obj, name, QOBJECT(qbool), errp); //查找对应的属性结构体,并执行结构体中的set方法 qobject_unref(qbool); //将obj->base.refcnt自减 return ok;}QBool *qbool_from_bool(bool value){
QBool *qb; qb = g_malloc(sizeof(*qb)); qobject_init(QOBJECT(qb), QTYPE_QBOOL); qb->value = value; //上边的操作为初始化QBool结构体对象qb return qb;}static inline void qobject_init(QObject *obj, QType type){
assert(QTYPE_NONE < type && type < QTYPE__MAX); obj->base.refcnt = 1; obj->base.type = type;}bool object_property_set_qobject(Object *obj, const char *name, QObject *value, Error **errp){
Visitor *v; bool ok; v = qobject_input_visitor_new(value); //创建Visitor结构体对象,并对其进行赋值 ok = object_property_set(obj, name, v, errp); //设置object对象的属性 visit_free(v); return ok;}Visitor *qobject_input_visitor_new(QObject *obj){
QObjectInputVisitor *v = qobject_input_visitor_base_new(obj); //创建QObjectInputVisitor结构体对象,并将obj->base.refcnt自增 v->visitor.type_int64 = qobject_input_type_int64; v->visitor.type_uint64 = qobject_input_type_uint64; v->visitor.type_bool = qobject_input_type_bool; v->visitor.type_str = qobject_input_type_str; v->visitor.type_number = qobject_input_type_number; v->visitor.type_any = qobject_input_type_any; v->visitor.type_null = qobject_input_type_null; return &v->visitor;}bool object_property_set(Object *obj, const char *name, Visitor *v, Error **errp){
Error *err = NULL; ObjectProperty *prop = object_property_find(obj, name, errp); //根据name获取OBJECT对应的ObjectProperty结构体对象 //查找过程中会从父类,子类,以及子对象中查找属性结构体 if (prop == NULL) {
return false; } if (!prop->set) {
error_setg(errp, QERRP_PERMISSION_DEFINES); return false; } prop->set(obj, v, name, prop->opaque, &err); //如果查找到,则执行属性结构体中的set方法 error_propagate(errp, err); return !err;}通过对上边代码的分析可知,当设置某一属性时,需要现将该属性进行添加,添加的接口为object_class_property_add_bool函数。(注意,这里只是以bool类型的属性为例,在qemu中存在其他不同类型的对应接口)ObjectProperty *object_class_property_add_bool(ObjectClass *klass, const char *name, bool (*get)(Object *, Error **), void (*set)(Object *, bool, Error **)){
BoolProperty *prop = g_malloc0(sizeof(*prop)); prop->get = get; prop->set = set; return object_class_property_add(klass, name, "bool", get ? property_get_bool : NULL, set ? property_set_bool : NULL, NULL, prop);}ObjectProperty *object_class_property_add(ObjectClass *klass, const char *name, const char *type, ObjectPropertyAccessor *get, ObjectPropertyAccessor *set, ObjectPropertyRelease *release, void *opaque){
ObjectProperty *prop; assert(!object_class_property_find(klass, name, NULL)); prop = g_malloc0(sizeof(*prop)); prop->name = g_strdup(name); prop->type = g_strdup(type); prop->get = get; prop->set = set; prop->release = release; prop->opaque = opaque; g_hash_table_insert(klass->properties, prop->name, prop); return prop;}以设备的“realized”属性为例,此时的set函数指针为device_set_realized,如下:static void device_set_realized(Object *obj, bool value, Error **errp){
DeviceState *dev = DEVICE(obj); DeviceClass *dc = DEVICE_GET_CLASS(dev); HotplugHandler *hotplug_ctrl; BusState *bus; NamedClockList *ncl; Error *local_err = NULL; bool unattached_parent = false; static int unattached_count; if (dev->hotlugged && !dc->hotpluggable) {
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj)); return; } if (value && !dev->realized) {
if (!check_only_migratable(obj, errp)) {
goto fail; } if (!obj->parent) {
gchar *name = g_strdup_printf("device[%d]", unattached_count++); object_property_add_child(container_get(qdev_get_machine(), "/unattached"), name, obj); unattached_parent = true; g_free(name); } hotplug_ctrl = qdev_get_hotplug_handler(dev); if (hotplug_ctrl) {
hotplug_handler_pre_plug(hotplug_ctrl, dev, &local_err); if (local_err != NULL) {
goto fail; } } if (dc->realize) {
dc->realize(dev, &local_err); if (local_err != NULL) {
goto fail; } } DEVICE_LISTENER_CALL(realize, Forward, dev); g_free(dev->canonical_path); dev->canonical_path = object_get_canonical_path(OBJECT(dev)); QLIST_FOREACH(ncl, &dev->clocks, node) {
if (ncl->alias) {
continue; } else {
clock_setup_canonical_path(ncl->clock); } } if (qdev_get_vmsd(dev)) {
if (vmstate_register_with_alias_id(VMSTATE_IF(dev), VMSTATE_INSTANCE_ID_ANY, qdev_get_vmsd(dev), dev, dev->instance_id_alias, dev->alias_required_for_version, &local_err) < 0) {
goto post_realize_fail; } } /* * Clear the reset state, in case the object was previously unrealized * with a dirty state. */ resettable_state_clear(&dev->reset); QLIST_FOREACH(bus, &dev->child_bus, sibling) {
if (!qbus_realize(bus, errp)) {
goto child_realize_fail; } } if (dev->hotplugged) {
/* * Reset the device, as well as its subtree which, at this point, * should be realized too. */ resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD); resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus), NULL); resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD); } dev->pending_deleted_event = false; if (hotplug_ctrl) {
hotplug_handler_plug(hotplug_ctrl, dev, &local_err); if (local_err != NULL) {
goto child_realize_fail; } } } else if (!value && dev->realized) {
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
qbus_unrealize(bus); } if (qdev_get_vmsd(dev)) {
vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); } if (dc->unrealize) {
dc->unrealize(dev); } dev->pending_deleted_event = true; DEVICE_LISTENER_CALL(unrealize, Reverse, dev); } assert(local_err == NULL); dev->realized = value; return;child_realize_fail: QLIST_FOREACH(bus, &dev->child_bus, sibling) {
qbus_unrealize(bus); } if (qdev_get_vmsd(dev)) {
vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); }post_realize_fail: g_free(dev->canonical_path); dev->canonical_path = NULL; if (dc->unrealize) {
dc->unrealize(dev); }fail: error_propagate(errp, local_err); if (unattached_parent) {
/* * Beware, this doesn't just revert * object_property_add_child(), it also runs bus_remove()! */ object_unparent(OBJECT(dev)); unattached_count--; }}在上边的代码中,可以看见会执行DeviceClass结构体中realize函数指针所指向的函数。该函数在初始DeviceClass时由开发者来实现,并附给类对象中realize变量。

转载地址:http://cpxii.baihongyu.com/

你可能感兴趣的文章
before start of result set 是什么错误
查看>>
(正则表达式)表单验证
查看>>
jsp...
查看>>
网页代码中用<%=request.getContextPath()%>和不用的区别?
查看>>
在JS中 onclick="save();return false;"return false是
查看>>
JSTL 常用标签总结
查看>>
内容里面带标签,在HTML显示问题,JSTL
查看>>
JDBC与JNDI这两种连接方式有什么区别?
查看>>
PHP day9 post接受数据 variable type error:array
查看>>
Java api 1.8 中文 帮助文档 各个翻译版本
查看>>
elasticsearch篇之mapping
查看>>
elasticsearch篇之SearchAPI
查看>>
kubernetes高可用架构
查看>>
[集群监控]使用Prometheus + grafana + node-exporter
查看>>
[集群监控]使用cAdvisor + Heapster + InfluxDB + Grafana
查看>>
Docker技术应用场景
查看>>
管理应用程序数据
查看>>
docker中搭建LNMP平台
查看>>
docker网络管理
查看>>
镜像仓库
查看>>