alloc_skb

–分配skb,进行基本的初始化;

 static inline struct sk_buff *alloc_skb(unsigned int size,
gfp_t priority)
{
return __alloc_skb(size, priority, , NUMA_NO_NODE);
}
 /**
* __alloc_skb - allocate a network buffer
* @size: size to allocate
* @gfp_mask: allocation mask
* @flags: If SKB_ALLOC_FCLONE is set, allocate from fclone cache
* instead of head cache and allocate a cloned (child) skb.
* If SKB_ALLOC_RX is set, __GFP_MEMALLOC will be used for
* allocations in case the data is required for writeback
* @node: numa node to allocate memory on
*
* Allocate a new &sk_buff. The returned buffer has no headroom and a
* tail room of at least size bytes. The object has a reference count
* of one. The return is the buffer. On a failure the return is %NULL.
*
* Buffers may only be allocated from interrupts using a @gfp_mask of
* %GFP_ATOMIC.
*/
struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
int flags, int node)
{
struct kmem_cache *cache;
struct skb_shared_info *shinfo;
struct sk_buff *skb;
u8 *data;
bool pfmemalloc; /* 得到分配使用的高速缓存 */
cache = (flags & SKB_ALLOC_FCLONE)
? skbuff_fclone_cache : skbuff_head_cache; if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX))
gfp_mask |= __GFP_MEMALLOC; /* Get the HEAD */
/* 分配skb */
skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
if (!skb)
goto out;
prefetchw(skb); /* We do our best to align skb_shared_info on a separate cache
* line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives
* aligned memory blocks, unless SLUB/SLAB debug is enabled.
* Both skb->head and skb_shared_info are cache line aligned.
*/
/* 数据对齐 */
size = SKB_DATA_ALIGN(size);
/* 对齐后的数据加上skb_shared_info对齐后的大小 */
size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); //分配数据区
data = kmalloc_reserve(size, gfp_mask, node, &pfmemalloc);
if (!data)
goto nodata;
/* kmalloc(size) might give us more room than requested.
* Put skb_shared_info exactly at the end of allocated zone,
* to allow max possible filling before reallocation.
*/
/* 除了skb_shared_info以外的数据大小 */
size = SKB_WITH_OVERHEAD(ksize(data));
prefetchw(data + size); /*
* Only clear those fields we need to clear, not those that we will
* actually initialise below. Hence, don't put any more fields after
* the tail pointer in struct sk_buff!
*/
memset(skb, , offsetof(struct sk_buff, tail));
/* Account for allocated memory : skb + skb->head */
/* 总长度= skb大小+ 数据大小+ skb_shared_info大小 */
skb->truesize = SKB_TRUESIZE(size);
/* PFMEMALLOC分配标记 */
skb->pfmemalloc = pfmemalloc;
/* 设置引用计数为1 */
atomic_set(&skb->users, );
/*head data tail均指向数据区头部*/
skb->head = data;
skb->data = data;
skb_reset_tail_pointer(skb); /* end指向数据区尾部 */
skb->end = skb->tail + size;
/* 初始化默认各层header偏移值 */
skb->mac_header = (typeof(skb->mac_header))~0U;
skb->transport_header = (typeof(skb->transport_header))~0U; /* make sure we initialize shinfo sequentially */
/* 从end开始的区域为skb_shared_info */
shinfo = skb_shinfo(skb);
memset(shinfo, , offsetof(struct skb_shared_info, dataref));
/* 设置引用计数为1 */
atomic_set(&shinfo->dataref, );
kmemcheck_annotate_variable(shinfo->destructor_arg); /* 如果有克隆标记 */
if (flags & SKB_ALLOC_FCLONE) {
struct sk_buff_fclones *fclones; /* 得到clone结构 */
fclones = container_of(skb, struct sk_buff_fclones, skb1); kmemcheck_annotate_bitfield(&fclones->skb2, flags1); /* 设置克隆标记 */
skb->fclone = SKB_FCLONE_ORIG; /* 设置引用为1 */
atomic_set(&fclones->fclone_ref, ); /* 设置skb2的克隆标记 */
fclones->skb2.fclone = SKB_FCLONE_CLONE;
}
out:
return skb;
nodata:
kmem_cache_free(cache, skb);
skb = NULL;
goto out;
}
dev_alloc_skb

–分配skb,通常被设备驱动用在中断上下文中,它是alloc_skb的封装函数,因为在中断处理函数中被调用,因此要求原子操作(GFP_ATOMIC);

 /* legacy helper around netdev_alloc_skb() */
static inline struct sk_buff *dev_alloc_skb(unsigned int length)
{
return netdev_alloc_skb(NULL, length);
}
 /**
* netdev_alloc_skb - allocate an skbuff for rx on a specific device
* @dev: network device to receive on
* @length: length to allocate
*
* Allocate a new &sk_buff and assign it a usage count of one. The
* buffer has unspecified headroom built in. Users should allocate
* the headroom they think they need without accounting for the
* built in space. The built in space is used for optimisations.
*
* %NULL is returned if there is no free memory. Although this function
* allocates memory it can be called from an interrupt.
*/
static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
unsigned int length)
{
return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
}
 /**
* __netdev_alloc_skb - allocate an skbuff for rx on a specific device
* @dev: network device to receive on
* @len: length to allocate
* @gfp_mask: get_free_pages mask, passed to alloc_skb
*
* Allocate a new &sk_buff and assign it a usage count of one. The
* buffer has NET_SKB_PAD headroom built in. Users should allocate
* the headroom they think they need without accounting for the
* built in space. The built in space is used for optimisations.
*
* %NULL is returned if there is no free memory.
*/
struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
gfp_t gfp_mask)
{
struct page_frag_cache *nc;
unsigned long flags;
struct sk_buff *skb;
bool pfmemalloc;
void *data; len += NET_SKB_PAD; /*
分配长度+ skb_shared_info长度> 一页
有__GFP_DIRECT_RECLAIM | GFP_DMA 标记
*/
if ((len > SKB_WITH_OVERHEAD(PAGE_SIZE)) ||
(gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
/* 通过__alloc_skb分配内存*/
skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE);
if (!skb)
goto skb_fail; /* 分配成功 */
goto skb_success;
} /* 分配长度+ skb_shared_info长度*/
len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
/* 对整个长度进行对齐 */
len = SKB_DATA_ALIGN(len); if (sk_memalloc_socks())
gfp_mask |= __GFP_MEMALLOC; /* 保存中断 */
local_irq_save(flags); nc = this_cpu_ptr(&netdev_alloc_cache);
/* 分配空间 */
data = page_frag_alloc(nc, len, gfp_mask);
pfmemalloc = nc->pfmemalloc; /* 恢复中断 */
local_irq_restore(flags); if (unlikely(!data))
return NULL; /* 构建skb */
skb = __build_skb(data, len);
if (unlikely(!skb)) {
skb_free_frag(data);
return NULL;
} /* use OR instead of assignment to avoid clearing of bits in mask */
/* 设置PFMEMALLOC标记 */
if (pfmemalloc)
skb->pfmemalloc = ; //打内存分配标记
skb->head_frag = ; skb_success:
/* 保留空间 */
skb_reserve(skb, NET_SKB_PAD);
/* 设置输入设备 */
skb->dev = dev; skb_fail:
return skb;
}
kfree_skb

–减少skb引用,为0则释放,用于出错丢包时释放skb使用;

 /**
* kfree_skb - free an sk_buff
* @skb: buffer to free
*
* Drop a reference to the buffer and free it if the usage count has
* hit zero.
*/
/*
释放skb
*/
void kfree_skb(struct sk_buff *skb)
{
if (unlikely(!skb))
return;
/* 引用为1,可直接释放 */
if (likely(atomic_read(&skb->users) == ))
smp_rmb();
/*
对引用减1,并且判断,如果结果不为0
说明还有引用,返回
*/
else if (likely(!atomic_dec_and_test(&skb->users)))
return;
trace_kfree_skb(skb, __builtin_return_address()); //真正的skb释放
__kfree_skb(skb);
}
 /**
* __kfree_skb - private function
* @skb: buffer
*
* Free an sk_buff. Release anything attached to the buffer.
* Clean the state. This is an internal helper function. Users should
* always call kfree_skb
*/
/* 释放skb */
void __kfree_skb(struct sk_buff *skb)
{
/* 释放skb附带的所有数据 */
skb_release_all(skb);
/* 释放skb */
kfree_skbmem(skb);
}
dev_kfree_skb && consume_skb

–减少skb引用,为0则释放,成功状态下释放skb使用;

 /**
* consume_skb - free an skbuff
* @skb: buffer to free
*
* Drop a ref to the buffer and free it if the usage count has hit zero
* Functions identically to kfree_skb, but kfree_skb assumes that the frame
* is being dropped after a failure and notes that
*/
/* 释放skb,与kfree_skb区别是,kfree_skb用于失败时丢包释放 */
void consume_skb(struct sk_buff *skb)
{
if (unlikely(!skb))
return;
if (likely(atomic_read(&skb->users) == ))
smp_rmb();
else if (likely(!atomic_dec_and_test(&skb->users)))
return;
trace_consume_skb(skb);
__kfree_skb(skb);
}
 #define dev_kfree_skb(a)    consume_skb(a)

skb管理函数之alloc_skb、dev_alloc_skb、kfree_skb、dev_kfree_skb、consume_skb的更多相关文章

  1. skb管理函数之skb_clone、pskb_copy、skb_copy

    skb_clone--只复制skb描述符本身,如果只修改skb描述符则使用该函数克隆: pskb_copy--复制skb描述符+线性数据区域(包括skb_shared_info),如果需要修改描述符以 ...

  2. skb管理函数之skb_put、skb_push、skb_pull、skb_reserve

    四个操作函数直接的区别,如下图: /** * skb_put - add data to a buffer * @skb: buffer to use * @len: amount of data t ...

  3. μC/OS-Ⅲ系统的时间管理函数和定时器

    一.时间管理函数 μC/OS-Ⅲ系统提供一些列时间管理服务函数: 1.OSTimeDly():任务延时n个时钟节拍. 2.OSTimeDlyHMSM():任务延时指定的时间,采用“时:分:秒:毫秒”方 ...

  4. 内存管理运算符new delete与内存管理函数malloc free的区别——已经他们对对象创建的过程。

    (1)内存管理函数与内存管理运算符的区别 内存管理函数有内存分配函数,malloc calloc realloc 以及内存释放函数free. 内存管理运算符有new 和delete. 两种内存管理方式 ...

  5. functools:管理函数工具(部分)

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #functools:管理函数工具 #作用:处理其他函数的函数 #版 ...

  6. POSIX多线程——基本线程管理函数介绍

    POSIX基本的几个线程管理函数见下表: ------------------------------------------------------------------------------- ...

  7. [图形学] Chp9 三维几何变换--栈处理函数与矩阵管理函数的区别

    矩阵管理函数:glLoadIdentity()是把当前活动矩阵设置为单位矩阵. 栈处理函数:glPushMatrix()是将当前活动的变换矩阵复制一份,压入栈顶:glPopMatrix()是破坏当前活 ...

  8. C++内存管理-重载内存管理函数

    记录学习的点点滴滴,参考侯捷<<C++内存管理>> 我们先重载一下C++的几个内存管理函数 operator new, operator new[], operator del ...

  9. 【教训】null == '',改造ThinkSNS 系统里面的一个缓存管理函数S()后,留下一个大bug

    本来想简化 ThinkSNS 系统里面的一个缓存管理函数: <?php /** * 用来对应用缓存信息的读.写.删除 * $expire = null/0 表示永久缓存,否则为缓存有效期 */ ...

随机推荐

  1. html5 canvas 图像处理

    1.图像放大缩小 <script> var cvs = document.getElementById("canvas"); cvs.width = cvs.heigh ...

  2. 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树

    题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...

  3. 【bzoj1672】[USACO2005 Dec]Cleaning Shifts 清理牛棚 dp/线段树

    题目描述 Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now ...

  4. BZOJ4240 有趣的家庭菜园(贪心+树状数组)

    显然相当于使序列变成单峰.给原序列每个数按位置标号,则要求重排后的序列原标号的逆序对数最少.考虑将数从大到小放进新序列,那么贪心的考虑放在左边还是右边即可,因为更小的数一定会在其两侧,与它自身放在哪无 ...

  5. [洛谷P5205]【模板】多项式开根

    题目大意:给你$n$项多项式$A(x)$,求出$B(x)$满足$B^2(x)\equiv A(x)\pmod{x^n}$ 题解:考虑已经求出$B_0(x)$满足$B_0^2(x)\equiv A(x) ...

  6. bzoj 2424: [HAOI2010]订货 (费用流)

    直接费用流,天数就是点数 type arr=record toward,next,cap,cost:longint; end; const maxm=; maxn=; mm=<<; var ...

  7. Android原生代码拦截H5 Web页面中JavaScript弹窗/弹框

    <html> <body> <script> function showAlert(){ alert("JavaScript - hello , worl ...

  8. BZOJ1568:[JSOI2008]Blue Mary开公司——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1568 李超线段树(不会的话去网上搜吧……). 完. #include<map> #in ...

  9. BZOJ3110:[ZJOI2013]K大数查询——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...

  10. Android Json解析与总结

    一.JSON定义 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Progra ...