qemu采用了模块机制。总共有5中模块定义在include/qemu/module.h 中
typedef enum {
MODULE_INIT_BLOCK,
MODULE_INIT_OPTS,
MODULE_INIT_QAPI,
MODULE_INIT_QOM,
MODULE_INIT_TRACE,
MODULE_INIT_MAX
} module_init_type;
#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
#define opts_init(function) module_init(function, MODULE_INIT_OPTS)
#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
#define type_init(function) module_init(function, MODULE_INIT_QOM)
#define trace_init(function) module_init(function, MODULE_INIT_TRACE)
这里以block为例
static BlockDriver bdrv_archipelago = {
.format_name = "archipelago",
.protocol_name = "archipelago",
.instance_size = sizeof(BDRVArchipelagoState),
.bdrv_parse_filename = archipelago_parse_filename,
.bdrv_file_open = qemu_archipelago_open,
};
static void bdrv_archipelago_init(void)
{
bdrv_register(&bdrv_archipelago);
}
block_init(bdrv_archipelago_init);
可见所以的block模块都会调用block_init。
#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
block_init 会调用module_init,只是type是MODULE_INIT_BLOCK
#define module_init(function, type) \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
register_module_init(function, type); \
}
可以看待所以的门口最终都会调用register_module_init,只是type不一样
void register_module_init(void (*fn)(void), module_init_type type)
{
ModuleEntry *e;
ModuleTypeList *l;
//申请一个ModuleEntry结构
e = g_malloc0(sizeof(*e));
//申请模块最重要的函数。最后会在module_call_init中被调用到
e->init = fn;
e->type = type;
//找到当前type的list
l = find_type(type);
//插入到这个list的最后
QTAILQ_INSERT_TAIL(l, e, node);
}
继续看看find_type
static ModuleTypeList *find_type(module_init_type type)
{
//初始化数组init_type_list。建立前面说的5中type的list的head
init_lists();
//每个不同的module type用init_type_list数组的index表示这中类型type的head
return &init_type_list[type];
}
与注册类似,会通过module_call_init来调用这5中模块的init函数
void module_call_init(module_init_type type)
{
ModuleTypeList *l;
ModuleEntry *e;
l = find_type(type);
QTAILQ_FOREACH(e, l, node) {
e->init();
}
}
qemu中的module
最新推荐文章于 2024-04-22 11:39:47 发布