QEMU模块模型

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chenglinhust/article/details/8603301
QEMU模块模型
#define module_init(function, type)                                         \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) {  \
    register_module_init(function, type);                                   \
}

typedef enum {
    MODULE_INIT_BLOCK,
    MODULE_INIT_MACHINE,
    MODULE_INIT_QAPI,
    MODULE_INIT_QOM,
    MODULE_INIT_MAX
} module_init_type;

#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
#define machine_init(function) module_init(function, MODULE_INIT_MACHINE)
#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
#define type_init(function) module_init(function, MODULE_INIT_QOM)

//创建init指向fn的ModuleEntry,并将其插入到链表init_type_list[type]尾部
void register_module_init(void (*fn)(void), module_init_type type);

//依次调用链表init_type_list[type]中所有ModuleEntry的函数指针init
void module_call_init(module_init_type type);

typedef struct ModuleEntry
{
    void (*init)(void);
    QTAILQ_ENTRY(ModuleEntry) node;
} ModuleEntry;

typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;

static ModuleTypeList init_type_list[MODULE_INIT_MAX];

如何完成模块的构造呢?下面以an5206机器模块构造为例进行说明:

static void an5206_init(ram_addr_t ram_size,
                     const char *boot_device,
                     const char *kernel_filename, const char *kernel_cmdline,
                     const char *initrd_filename, const char *cpu_model)
{
    ...
}

static QEMUMachine an5206_machine = {
    .name = "an5206",
    .desc = "Arnewsh 5206",
    .init = an5206_init,
};

static void an5206_machine_init(void)
{
    qemu_register_machine(&an5206_machine);
}

machine_init(an5206_machine_init);

由于带有__attribute__((constructor))属性,表示在main函数之前执行,所以
    machine_init(an5206_machine_init);
作用是在main之前在链表init_type_list[MODULE_INIT_MACHINE]中插入一个ModuleEntry元素,其init指针指向an5206_machine_init

在main函数中,执行下面语句时,
    module_call_init(MODULE_INIT_MACHINE);
间接调用了an5206_machine_init();
也就是说将an5206_machine注册到了QEMUMachine链表(first_machine)中。

于是对QEMUMachine链表中元素,调用下面语句进行初始化。
machine->init(ram_size, boot_devices,kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
如果machine指向的是an5206_machine,上面语句就相当于:
an5206_machine.an5206_init(ram_size, boot_devices,kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
展开阅读全文

没有更多推荐了,返回首页