基本知识:
在内核 编程中,可能经常会有一些数据结构需要反复使用和释放,按照通常的思路,可能是使用kmalloc和kfree来实现。
但是这种方式效率不高,Linux为我们提供了更加高效的方法——Slab高速缓存管理器。
动态创建固定大小的内存对象,虽然kmalloc的时间复杂度并不大,但是联系到空间复杂度,还是采用kmem_cache_alloc的好;而非固定大小的内存申请,只能经由kmalloc来解决。
xfrm_input.c中关于kmem_cache_alloc的代码:(按文件中代码的顺序)
先是声明了一个struct kmem_cache类型的结构体:
static struct kmem_cache *secpath_cachep __read_mostly;
接下来是释放操作函数:
void __secpath_destroy(struct sec_path *sp)
{
int i;
for (i = 0; i < sp->len; i++)
xfrm_state_put(sp->xvec[i]);
kmem_cache_free(secpath_cachep, sp);
}
EXPORT_SYMBOL(__secpath_destroy);
使用kmem_cache_alloc为一个struct sec_path结构体分配空间:
struct sec_path *secpath_dup(struct sec_path *src)
{
struct sec_path *sp;
sp = kmem_cache_alloc(secpath_cachep, GFP_ATOMIC);
if (!sp)
return NULL;
sp->len = 0;
if (src) {
int i;
memcpy(sp, src, sizeof(*sp));
for (i = 0; i < sp->len; i++)
xfrm_state_hold(sp->xvec[i]);
}
atomic_set(&sp->refcnt, 1);
return sp;
}
EXPORT_SYMBOL(secpath_dup);
调用secpath_dup()指针函数获得指向分配好的struct sec_path结构体指针:
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
{
。。。。。。
/* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
struct sec_path *sp;
sp = secpath_dup(skb->sp);
if (!sp) {
XFRM_INC_STATS(LINUX_MIB_XFRMINERROR);
goto drop;
}
if (skb->sp)
secpath_put(skb->sp);
skb->sp = sp;
}
。。。。。。
}
初始化函数,获得指向高速缓存struct kmem_cache结构体指针secpath_cachep,这个函数也在~/include/net/xfrm.h
中进行了声明,另外~/net/xfrm/xfrm_policy.c的初始化函数xfrm_init()在调用 xfrm_state_init();和 xfrm_policy_init();
函数时,也调用了xfrm_input_init()函数;
void __init xfrm_input_init(void)
{
secpath_cachep = kmem_cache_create("secpath_cache",
sizeof(struct sec_path),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
NULL);
}
实际代码执行顺序是这样的:
static struct kmem_cache *secpath_cachep __read_mostly;
xfrm_input_init()--> secpath_cachep = kmem_cache_create("secpath_cache",
sizeof(struct sec_path),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
NULL);
到这里我们获得了一个可用的secpath_cachep头指针
接下来
xfrm_input()-->secpath_dup()-->struct sec_path *sp; sp = kmem_cache_alloc(secpath_cachep, GFP_ATOMIC);
这样我们就可以使用sp指针来存储struct sec_path结构体的内容了。
顺便说一下struct sec_path
{
atomic_t refcnt;
int len;
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
};
这个结构体也是struct sk_buff的成员之一,它包含了指向SA的指针数组struct xfrm_state *xvec[XFRM_MAX_DEPTH],
记录了在IPsec进入处理过程中,依次应用于信报处理的SA及其相关信息。
参考:
http://linux.chinaunix.net/bbs/viewthread.php?tid=913690
http://blog.chinaunix.net/u/5251/showart_402033.html