qemu中的module

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();
    }
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值