C程序不全是从main开始的 — 以QEMU中qcow2模块初始化为例

0. GCC的attribute关键字

这是GCC的一个特性,gcc可以使用attribute关键字,格式如下:

其中attribute_name中有两类constructordestructor类似C++中类的构造和析构的概念,只不过是相对main()函数来说的。简单说,__attribute__((constructor))定义的函数在main前执行,__attribute__((destructor))定义的函数在main后执行。

1. 以qcow2为例

QEMU中有很多”module”的初始化使用了__attribute__((constructor))这个特性,来在main前完成init函数的注册过程。使用方法举例具体如下:

下面以qcow2这个模块的初始化为例介绍下:

Step 1. main函数前执行constructor

第一步利用gcc支持的“构造函数”,将qcow2的初始化函数“注册”:

util/module.c中有这样一句:static ModuleTypeList init_type_list[MODULE_INIT_MAX];
可以看到在这之后最终函数指针fn通过变量e和宏函数QTAILQ_INSERT_TAIL(l, e, node)被存入事先定义的全局数组init_type_list中的type链表(这里type是MODULE_INIT_BLOCK)中。我们继续看main函数:

Step 2. main函数中进行init

调用流程如下:

我们看到虽然module_call_init(MODULE_INIT_BLOCK)和上边step 1.中的register_module_init(function, type)函数都在util/module.c中,但是调用的时机是不同的,step1中的register注册模块,step2中的call才是在真正调用init函数,而step1是在main前执行的,step2是在main函数中执行的。


[1] __ATTRIBUTE__ 你知多少?, http://www.cnblogs.com/astwish/articles/3460618.html

[2] QEMU在main函数前对模块的初始化过程, http://blog.csdn.net/u011364612/article/details/53581501

发表评论

电子邮件地址不会被公开。 必填项已用*标注