FRR - 基础数据结构篇 - 数据结构和内存分配 memory.c

基本数据结构

1:memtype

//基础数据结构最后都会被封装成这个结构
struct memtype {
	struct memtype *next, **ref;
	const char *name;                //结构描述名
	atomic_size_t n_alloc;           //申请内存的长度
	atomic_size_t n_max;
	atomic_size_t size;              //已用长度
#ifdef HAVE_MALLOC_USABLE_SIZE
	atomic_size_t total;
	atomic_size_t max_size;
#endif
};

//其中atomic_size_t 即 volatile  size_t
typedef _Atomic size_t		atomic_size_t;
#define _Atomic volatile

2:memgroup

struct memgroup {
	struct memgroup *next, **ref;
	struct memtype *types, **insert;
	const char *name;                      //组名
	/* ignore group on dumping memleaks at exit */
	bool active_at_exit;
};

方法

1:结构体声明初始化

//结构extern申明
#define DECLARE_MTYPE(name)                                                    \
	extern struct memtype MTYPE_##name[1];                                 \
	/* end */

#define DEFINE_MTYPE_ATTR(group, mname, attr, desc)                            \
         //结构声明,并初始化在.data.mtypes数据段中
	attr struct memtype MTYPE_##mname[1]                                   \
		__attribute__((section(".data.mtypes"))) = { {                 \
			.name = desc,                                          \
			.next = NULL,                                          \
			.n_alloc = 0,                                          \
			.size = 0,                                             \
			.ref = NULL,                                           \
	} };                                                                   \
        //在main前指定优先级1001执行该函数
	static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \
	static void _mtinit_##mname(void)                                      \
	{                                                                      \
		if (_mg_##group.insert == NULL)                                \
			_mg_##group.insert = &_mg_##group.types;               \
		MTYPE_##mname->ref = _mg_##group.insert;                       \
		*_mg_##group.insert = MTYPE_##mname;                           \
		_mg_##group.insert = &MTYPE_##mname->next;                      \
	}                                                                      \
	static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001)));  \
	static void _mtfini_##mname(void)                                      \
	{                                                                      \
		if (MTYPE_##mname->next)                                       \
			MTYPE_##mname->next->ref = MTYPE_##mname->ref;         \
		*MTYPE_##mname->ref = MTYPE_##mname->next;                     \
	}                                                                      \
	/* end */

#define DEFINE_MTYPE(group, name, desc)                                        \
	DEFINE_MTYPE_ATTR(group, name, , desc)                                 \
	/* end */

#define DEFINE_MTYPE_STATIC(group, name, desc)                                 \
	DEFINE_MTYPE_ATTR(group, name, static, desc)                           \
	/* end */

其中:

1:使用__attribute__((section()))构建初始化函数表,由模块告知main:“我要初始化“,添加新模块再也不需要在main代码中显式调用模块初始化接口。以此实现main与模块之间的隔离,main不再关心有什么模块,模块的删减也不需要修改main。

       模块通过__attribute__((section("name")))的实现,在编译时把初始化的接口放到name数据段中。main在执行初始化时并不需要知道有什么模块需要初始化,只需要把name数据段中的所有初始化接口执行一遍即可

        __attribute__((section(”name“)))是gcc编译器支持的一个编译特性(arm编译器也支持此特性),实现在编译时把某个函数/数据放到name的数据段中。

2:__attribute__((constructor(preference))) 先于main()函数调用  

具体可参考__attribute__((constructor))和__attribute__((destructor)) 。

2:内存分配 

//用calloc分配size大小内存块
#define XCALLOC(mtype, size)		qcalloc(mtype, size)

void *qcalloc(struct memtype *mt, size_t size)
{
    //用calloc分配size个长度为1字节的内存,赋给函数mt_checkalloc的ptr
	return mt_checkalloc(mt, calloc(size, 1), size);
}

static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size)
{
    //(ptr == NULL) == 0的概率很大,即calloc一般不会分配失败
	if (__builtin_expect(ptr == NULL, 0)) {
		if (size) {
			/* malloc(0) is allowed to return NULL */
			memory_oom(size, mt->name);
		}
		return NULL;
	}

    //内存分配成功,对mt内数据结构的数值进行原子跟新
	mt_count_alloc(mt, size, ptr);
	return ptr;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值