__attribute__((__used__)) 和 __attribute__((__section__(“*“ “*“)))的使用

3 篇文章 0 订阅
1 篇文章 0 订阅

见:haproxy代码

C语言注册函数和调用函数,便于模块化开发和编程。

#include <stdio.h>

#ifdef __APPLE__
#define HA_SECTION(s)           __attribute__((__section__("__DATA, " s)))
#define HA_SECTION_START(s)     __asm("section$start$__DATA$" s)
#define HA_SECTION_STOP(s)      __asm("section$end$__DATA$" s)
#else
#define HA_SECTION(s)           __attribute__((__section__(s)))
#define HA_SECTION_START(s)
#define HA_SECTION_STOP(s)
#endif

/*
 * Please keep those names short enough, they are used to generate section
 * names, Mac OS X accepts section names up to 16 characters, and we prefix
 * them with i_, so stage name can't be more than 14 characters.
 */
enum init_stage {
	STG_PREPARE = 0,      // preset variables, tables, list heads
	STG_LOCK,             // pre-initialize locks
	STG_REGISTER,         // register static lists (keywords etc)
	STG_ALLOC,            // allocate required structures
	STG_POOL,             // create pools
	STG_INIT,             // subsystems normal initialization
	STG_SIZE              // size of the stages array, must be last
};

/* This is the descriptor for an initcall */
struct initcall {
	void (*const fct)(void *arg1, void *arg2, void *arg3);
	void *arg1;
	void *arg2;
	void *arg3;
#if defined(USE_OBSOLETE_LINKER)
	void *next;
#endif
};

/* declare a symbol as global */
#define __HA_GLOBL(sym)   __asm__(".globl " #sym)
#define HA_GLOBL(sym)     __HA_GLOBL(sym)

#define HA_INIT_SECTION(s)  HA_SECTION("i_" # s)

#define __DECLARE_INITCALL(stg, linenum, function, a1, a2, a3)     \
        HA_GLOBL(__start_i_##stg );                                \
        HA_GLOBL(__stop_i_##stg );                                 \
	static const struct initcall *__initcb_##linenum           \
	    __attribute__((__used__)) HA_INIT_SECTION(stg) =	   \
	        (stg < STG_SIZE) ? &(const struct initcall) {      \
		.fct = (void (*)(void *,void *,void *))function,   \
		.arg1 = (void *)(a1),                              \
		.arg2 = (void *)(a2),                              \
		.arg3 = (void *)(a3),                              \
	} : NULL

#define _DECLARE_INITCALL(...) \
	__DECLARE_INITCALL(__VA_ARGS__)

#define INITCALL0(stage, function)  \
	_DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)

/* Declare func */
#define DECLARE_INIT_SECTION(stg)                                                   \
	extern __attribute__((__weak__)) const struct initcall *__start_i_##stg HA_SECTION_START("i_" # stg); \
	extern __attribute__((__weak__)) const struct initcall *__stop_i_##stg  HA_SECTION_STOP("i_" # stg)

#define FOREACH_INITCALL(p,stg)                                               \
	for ((p) = &(__start_i_##stg); (p) < &(__stop_i_##stg); (p)++)

#define RUN_INITCALLS(stg)                                                     \
	do {                                                                   \
		const struct initcall **ptr;                                   \
		if (stg >= STG_SIZE)                                           \
			break;                                                 \
		FOREACH_INITCALL(ptr, stg)                                     \
			(*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
	} while (0)

/* register func1 */
static void _do_register_func1(void)
{
    printf("TEST: _do_register_func1()\n");
}
#if 0
__asm__(".globl " "__start_i_STG_REGISTER"); 
__asm__(".globl " "__stop_i_STG_REGISTER"); 
static const struct initcall *__initcb_405 __attribute__((__used__)) __attribute__((__section__("i_" "STG_REGISTER"))) = (STG_REGISTER < STG_SIZE) ? &(const struct initcall) 
{ 
    .fct = (void (*)(void *,void *,void *))_do_register, 
    .arg1 = (void *)(0), 
    .arg2 = (void *)(0), 
    .arg3 = (void *)(0), 
} : ((void *)0);
#endif
INITCALL0(STG_REGISTER, _do_register_func1);

/* register func2 */
static void _do_register_func2(void)
{
    printf("TEST: _do_register_func2()\n");
}
INITCALL0(STG_REGISTER, _do_register_func2);

/* register func3 */
static void _do_register_func3(void)
{
    printf("TEST: _do_register_func3()\n");
}
INITCALL0(STG_REGISTER, _do_register_func3);

/* declare func1, func2, func3 */
DECLARE_INIT_SECTION(STG_REGISTER);

int main(int argc, char *const argv[])
{
    /* call func1, func2, func3 */
    RUN_INITCALLS(STG_REGISTER);

    printf("hello world\n");
    return 0;
}

编译和运行:

ubuntu@dev:test-06$ gcc test1.c
ubuntu@dev:test-06$ ./a.out 
TEST: _do_register_func1()
TEST: _do_register_func2()
TEST: _do_register_func3()
hello world

不使用__attribute__((used)) 和 attribute((section(““ ““)))

#include <stdio.h>

/* register func1 */
static void _do_register_func1(void)
{
    printf("TEST: _do_register_func1()\n");
}

/* register func2 */
static void _do_register_func2(void)
{
    printf("TEST: _do_register_func2()\n");
}

/* register func3 */
static void _do_register_func3(void)
{
    printf("TEST: _do_register_func3()\n");
}

int main(int argc, char *const argv[])
{
    /* call func1, func2, func3 */
    _do_register_func1();
    _do_register_func2();
    _do_register_func3();

    printf("hello world\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值