关于raspi3的注册分析

关于raspi3的注册分析

1.raspi3_machine_init

1.1 binclude/hw/arm/raspi.c

static void raspi3_machine_init(MachineClass *mc)
{
    mc->desc = "Raspberry Pi 3";
    mc->init = raspi3_init;
    mc->block_default_type = IF_SD;
    mc->no_parallel = 1;
    mc->no_floppy = 1;
    mc->no_cdrom = 1;
    mc->max_cpus = BCM283X_NCPUS;
    mc->min_cpus = BCM283X_NCPUS;
    mc->default_cpus = BCM283X_NCPUS;
    mc->default_ram_size = 1 * GiB;
}
DEFINE_MACHINE("raspi3", raspi3_machine_init)

1.2 DEFINE_MACHINE

DEFINE_MACHINE宏定义在include/hw/boards.h,效果等同于:

static void raspi3_machine_init_class_init(ObjectClass *oc, void *data) 
{ 
        MachineClass *mc = ((MachineClass *)object_class_dynamic_cast_assert(((ObjectClass *)((oc))), ("machine"),                                                "/home/linux/qemu/hw/arm/raspi.c", 259, __func__)); 
        raspi3_machine_init(mc); 
} 

static const TypeInfo raspi3_machine_init_typeinfo = {
        .name       = ("raspi3" "-machine"), 
        .parent     = "machine", 
        .class_init = raspi3_machine_init_class_init, 
}; 

static void raspi3_machine_init_register_types(void) 
{ 
        type_register_static(&raspi3_machine_init_typeinfo); 
} 

static void __attribute__((constructor)) do_qemu_init_raspi3_machine_init_register_types(void)
{                                                                          
    register_module_init(raspi3_machine_init_register_types, MODULE_INIT_QOM);           
}

关于__attribute__((constructor))

The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () completes or exit () is called. Functions with these attributes are useful for initializing data that is used implicitly during the execution of the program.

翻译

constructor属性使当前的函数在执行main函数前会自动的调用。类似的,destructor属性在main函数执行过后或者exit()被调用的时候进行调用。拥有这些属性的函数可以在执行程序过程中隐式地初始化数据。

可知在main函数初始化前,会调用do_qemu_init_raspi3_machine_init_register_types,然后调用register_module_init

1.3 register_module_init

register_module_init定义在/util/module.c

void register_module_init(void (*fn)(void), module_init_type type)
{
    ModuleEntry *e;
    ModuleTypeList *l;

    e = g_malloc0(sizeof(*e));
    e->init = fn;
    e->type = type;

    l = find_type(type);

    QTAILQ_INSERT_TAIL(l, e, node);
}
//QTAILQ_INSERT_TAIL等价于
/*
do {                       
        (e)->node.tqe_next = (void *)0;                                   
        (e)->node.tqe_circ.tql_prev = (l)->tqh_circ.tql_prev;     
        (l)->tqh_circ.tql_prev->tql_next = (e);                    
        (l)->tqh_circ.tql_prev = &(e)->node.tqe_circ;             
} while (/*CONSTCOND*/0)
*/

在本启动中,fn是raspi3_machine_init_register_types的地址,这个地址赋值给e->inite->type为QOM

Created with Raphaël 2.2.0 register_module_init e->init = fn,fn为raspi3_machine_init_register_types的地址;,e->type = type;type值为QOM find_type函数找到QOM的ModuleTypeList头部,并将地址的值赋值给l 结束

关于struct ModuleEntry

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

关于module_init_type

typedef enum {
    MODULE_INIT_BLOCK,
    MODULE_INIT_OPTS,
    MODULE_INIT_QOM,
    MODULE_INIT_TRACE,
    MODULE_INIT_XEN_BACKEND,
    MODULE_INIT_LIBQOS,
    MODULE_INIT_MAX
} module_init_type;

QTAILQ_ENTRY(ModuleEntry) node等同于:

union {                                                                 
        struct ModuleEntry *tqe_next;        /* next element */                
        QTailQLink tqe_circ;          /* link for circular backwards list */ 
}

关于QOM

QEMU提供了一套面向对象编程的模型——QOM,即QEMU Object Module,几乎所有的设备如CPU、内存、总线等都是利用这一面向对象的模型来实现的。QOM模型的实现代码位于qom/文件夹下的文件中。

参考:https://blog.csdn.net/u011364612/article/details/53485856 (未细看)

find_type解析:

static ModuleTypeList dso_init_list;
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;

ModuleTypeList等同于:

union  {                                                            
        struct ModuleEntry *tqh_first;       /* first element */               
        QTailQLink tqh_circ;          /* link for circular backwards list */ 
}
static ModuleTypeList *find_type(module_init_type type)
{
    //
    init_lists();

    return &init_type_list[type];
}

static void init_lists(void)
{
    static int inited;
    int i;

    if (inited) {
        return;
    }

    for (i = 0; i < MODULE_INIT_MAX; i++) {
        QTAILQ_INIT(&init_type_list[i]);
    }

    QTAILQ_INIT(&dso_init_list);

    inited = 1;
}

QTAILQ_INIT(&init_type_list[i]);等价于:

do {                                          
        (&init_type_list[i])->tqh_first = (void *)0;                                       
        (&init_type_list[i])->tqh_circ.tql_prev = &(&init_type_list[i])->tqh_circ;                  
} while (/*CONSTCOND*/0)

QTAILQ_INIT(&dso_init_list);等价于

do {                                          
        (&dso_init_list)->tqh_first = (void *)0;                                       
        (&dso_init_list)->tqh_circ.tql_prev = &(&dso_init_list)->tqh_circ;              
} while (/*CONSTCOND*/0)

1.4 总结

相当于在init_type_list[QOM]中注册了raspi3_machine_init_register_types所在的地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值