一文看懂linux 内核网络 sk_buff 之申请和释放

本文详细介绍了Linux内核中sk_buff的内存申请和释放过程,包括__alloc_skb()和kfree_skb()函数的使用。讲解了如何通过alloc_skb_fclone()为可能需要克隆的sk_buff分配内存,并讨论了内存分配策略和缓存池的作用,确保高效且减少内存碎片。同时阐述了sk_buff释放时的引用计数检查和释放条件。
摘要由CSDN通过智能技术生成

1 sk_buff 内存申请接口概述

因为 sk_buff 结构是比较复杂的(并不是其本身结构复杂,而是其所指的数据区以及分片结构等,合在一起就变复杂了),所以在内存申请和释放时,就要搞清楚什么函数对应的申请分配或释放什么结构内存。这里不提倡自己用 kmalloc() 和 kfree() 函数来为 sk_buff 相关结构体申请内存及销毁,而要用内核提供好的一些函数去为这些结构体申请内存。内核开发的原则:尽量用内核定义好的数据和函数以及操作宏,不到迫不得已不要自行定义任何东西。这样做是为了接口统一,移植方便,容易维护。

static inline struct sk_buff *alloc_skb(unsigned int size,
					gfp_t priority)
{
	return __alloc_skb(size, priority, 0, NUMA_NO_NODE);
}
 
static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
					       gfp_t priority)
{
	return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE);
}
 
/* legacy helper around netdev_alloc_skb() */
static inline struct sk_buff *dev_alloc_skb(unsigned int length)
{
	return netdev_alloc_skb(NULL, length);
}
 
static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
					       unsigned int length)
{
	return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
}
 
struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
				   unsigned int length, gfp_t gfp_mask)
{
	struct sk_buff *skb = NULL;
	unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) +
			      SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
	if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) {
		void *data;
 
		if (sk_memalloc_socks())
			gfp_mask |= __GFP_MEMALLOC;
 
		data = __netdev_alloc_frag(fragsz, gfp_mask);
 
		if (likely(data)) {
			skb = build_skb(data, fragsz);
			if (unlikely(!skb))
				put_page(virt_to_head_page(data));
		}
	} else {
		skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask,
				  SKB_ALLOC_RX, NUMA_NO_NODE);
	}
	if (likely(skb)) {
		skb_reserve(skb, NET_SKB_PAD);
		skb->dev = dev;
	}
	return skb;
}

这几个函数都是在sk_buff.h文件中的,其实就函数也可以看得出这是内联函数。不记得在前面讲过没,对于简洁常用的函数一般都定义为内联函数,这样做是为了提高CPU工作效率和内存利用率。一般的函数调用要保存现场(在堆栈中保存调用函数时现场状态,包括地址,执行状态等);当调用函数完后,又要恢复现场状态(把开始保存的状态数据从堆栈中读取出来)。在调用函数和返回时,浪费了CPU很多时间,再个在存储时也会出现些碎片。所以再使用简洁函数时,一般定义为内联函数,在函数前面加个inline关键字。

alloc_skb():是用来分配单纯的sk_buff结构内存的࿰

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值