内核IPSec代码中xfrm_input.c中关于kmem_cache_alloc的使用分析

基本知识:

内核 编程中,可能经常会有一些数据结构需要反复使用和释放,按照通常的思路,可能是使用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

 

 

你可能感兴趣的:(数据结构,cache,struct,null,input,Path)