建筑公司网站模板,wordpress 评论调用,苏州苏州最新的,sem是什么意思中文接前一篇文章#xff1a;QEMU源码全解析22 —— QOM介绍#xff08;11#xff09; 本文内容参考#xff1a;
《趣谈Linux操作系统》 —— 刘超#xff0c;极客时间
《QEMU/KVM》源码解析与应用 —— 李强#xff0c;机械工业出版社
特此致谢#xff01; 上一回分析了…接前一篇文章QEMU源码全解析22 —— QOM介绍11 本文内容参考
《趣谈Linux操作系统》 —— 刘超极客时间
《QEMU/KVM》源码解析与应用 —— 李强机械工业出版社
特此致谢 上一回分析了QEMU对象的构造和初始化的函数调用流程本回结合实例对此流程进行深入介绍和解析。
仍以前文的edu的TypeInfo为例。再次贴出edu相关代码如下hw/misc/edu.c中
static void pci_edu_register_types(void)
{static InterfaceInfo interfaces[] {{ INTERFACE_CONVENTIONAL_PCI_DEVICE },{ },};static const TypeInfo edu_info {.name TYPE_PCI_EDU_DEVICE,.parent TYPE_PCI_DEVICE,.instance_size sizeof(EduState),.instance_init edu_instance_init,.class_init edu_class_init,.interfaces interfaces,};type_register_static(edu_info);
}
type_init(pci_edu_register_types)
edu的对象大小为sizeof(EduState)因此实际上一个edu类型的对象是EduState结构体每一个对象都会有一个XXXState与之对应记录了该对象的相关信息。若edu是一个PCI设备则EduState中就会有这个设备的一些信息如中断信息、设备状态、使用的MMIO和PIO对应的内存区域等。
在object_init_with_type函数中可以看到调用的参数都是一个Object却能够一直调用父类型的初始化函数不出意外这里也会有一个层次关系。为了便于理解再次贴出相关代码
static void object_init_with_type(Object *obj, TypeImpl *ti)
{if (type_has_parent(ti)) {object_init_with_type(obj, type_get_parent(ti));}if (ti-instance_init) {ti-instance_init(obj);}
}
具体来看一下EduState结构其定义在hw/misc/edu.c中如下所示
struct EduState {PCIDevice pdev;MemoryRegion mmio;QemuThread thread;QemuMutex thr_mutex;QemuCond thr_cond;bool stopping;uint32_t addr4;uint32_t fact;
#define EDU_STATUS_COMPUTING 0x01
#define EDU_STATUS_IRQFACT 0x80uint32_t status;uint32_t irq_status;#define EDU_DMA_RUN 0x1
#define EDU_DMA_DIR(cmd) (((cmd) 0x2) 1)
# define EDU_DMA_FROM_PCI 0
# define EDU_DMA_TO_PCI 1
#define EDU_DMA_IRQ 0x4struct dma_state {dma_addr_t src;dma_addr_t dst;dma_addr_t cnt;dma_addr_t cmd;} dma;QEMUTimer dma_timer;char dma_buf[DMA_SIZE];uint64_t dma_mask;
};
关注其中第一个成员的类型PCIDevice结构。其与pci_device_type_info对应代码如下hw/pci/pci.c中
static const TypeInfo pci_device_type_info {.name TYPE_PCI_DEVICE,.parent TYPE_DEVICE,.instance_size sizeof(PCIDevice),.abstract true,.class_size sizeof(PCIDeviceClass),.class_init pci_device_class_init,.class_base_init pci_device_class_base_init,
};
struct PCIDevice在include/hw/pci/pci.h中定义代码如下
struct PCIDevice {DeviceState qdev;bool partially_hotplugged;bool has_power;/* PCI config space */uint8_t *config;/* Used to enable config checks on load. Note that writable bits are* never checked even if set in cmask. */uint8_t *cmask;/* Used to implement R/W bytes */uint8_t *wmask;/* Used to implement RW1C(Write 1 to Clear) bytes */uint8_t *w1cmask;/* Used to allocate config space for capabilities. */uint8_t *used;/* the following fields are read only */int32_t devfn;/* Cached device to fetch requester ID from, to avoid the PCI* tree walking every time we invoke PCI request (e.g.,* MSI). For conventional PCI root complex, this field is* meaningless. */PCIReqIDCache requester_id_cache;char name[64];PCIIORegion io_regions[PCI_NUM_REGIONS];AddressSpace bus_master_as;MemoryRegion bus_master_container_region;MemoryRegion bus_master_enable_region;/* do not access the following fields */PCIConfigReadFunc *config_read;PCIConfigWriteFunc *config_write;/* Legacy PCI VGA regions */MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];bool has_vga;/* Current IRQ levels. Used internally by the generic PCI code. */uint8_t irq_state;/* Capability bits */uint32_t cap_present;/* Offset of MSI-X capability in config space */uint8_t msix_cap;/* MSI-X entries */int msix_entries_nr;/* Space to store MSIX table pending bit array */uint8_t *msix_table;uint8_t *msix_pba;/* May be used by INTx or MSI during interrupt notification */void *irq_opaque;MSITriggerFunc *msi_trigger;MSIPrepareMessageFunc *msi_prepare_message;MSIxPrepareMessageFunc *msix_prepare_message;/* MemoryRegion container for msix exclusive BAR setup */MemoryRegion msix_exclusive_bar;/* Memory Regions for MSIX table and pending bit entries. */MemoryRegion msix_table_mmio;MemoryRegion msix_pba_mmio;/* Reference-count for entries actually in use by driver. */unsigned *msix_entry_used;/* MSIX function mask set or MSIX disabled */bool msix_function_masked;/* Version id needed for VMState */int32_t version_id;/* Offset of MSI capability in config space */uint8_t msi_cap;/* PCI Express */PCIExpressDevice exp;/* SHPC */SHPCDevice *shpc;/* Location of option rom */char *romfile;uint32_t romsize;bool has_rom;MemoryRegion rom;uint32_t rom_bar;/* INTx routing notifier */PCIINTxRoutingNotifier intx_routing_notifier;/* MSI-X notifiers */MSIVectorUseNotifier msix_vector_use_notifier;MSIVectorReleaseNotifier msix_vector_release_notifier;MSIVectorPollNotifier msix_vector_poll_notifier;/* ID of standby device in net_failover pair */char *failover_pair_id;uint32_t acpi_index;
};
同样关注第一个成员的类型DeviceState结构。其与device_type_info对应代码如下hw/core/qdev.c
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),.interfaces (InterfaceInfo[]) {{ TYPE_VMSTATE_IF },{ TYPE_RESETTABLE_INTERFACE },{ }}
};
struct DeviceState在include/hw/qdev-core.h中定义代码如下
/*** DeviceState:* realized: Indicates whether the device has been fully constructed.* When accessed outside big qemu lock, must be accessed with* qatomic_load_acquire()* reset: ResettableState for the device; handled by Resettable interface.** This structure should not be accessed directly. We declare it here* so that it can be embedded in individual device state structures.*/
struct DeviceState {/* private */Object parent_obj;/* public */char *id;char *canonical_path;bool realized;bool pending_deleted_event;int64_t pending_deleted_expires_ms;QDict *opts;int hotplugged;bool allow_unplug_during_migration;BusState *parent_bus;QLIST_HEAD(, NamedGPIOList) gpios;QLIST_HEAD(, NamedClockList) clocks;QLIST_HEAD(, BusState) child_bus;int num_child_bus;int instance_id_alias;int alias_required_for_version;ResettableState reset;GSList *unplug_blockers;
};
通过以上edu_info、pci_device_type_info、device_type_info和与之对应的EduState、PCIDevice、DeviceState的定义可以看出对象之间其实也是有一种父对象与子对象的关系存在。与类型一样QOM中的对象也可以使用宏将一个指向Object对象的指针转换成一个指向子类对象的指针转换过程与类型ObjectClass类似在此不在赘述。
这里可以看出不同于类型信息和类型object是根据需要创建的只有在命令行指定了设备或者是热插拔一个设备之后才会有object的创建。类型和对象之间是通过Object的Class域联系在一起的。这是在object_initialize_with_type函数中通过obj-class type-class实现的。对应代码再次贴出qom/object.c中
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_post_init_with_type(obj, type);
}
综合前文从QEMU源码全解析 —— QOM介绍1开始可以把QOM的对象构造成三部分第一部分是类型的构造通过TypeInfo构造一个TypeImpl的哈希表这是在主函数main之前完成的第二部分是类型的初始化这两部分都是全局的即只要编译进去的QOM对象都会被调用第三部分是类对象的构造这是构造具体的对象实例只有在命令行指定了对应的设备时才会创建对象。
类比C、Java等高级语言中的反射机制