linux内核源码分析 释放内存 “每日读书”

释放内存:kfree_skbdev_kfree_skb

两个函数会释放一个缓冲区使返回缓冲池kfree_skb直接dev_kfree_skb包裹函数调用启动随后设备驱动程序定义并使用名称dev_alloc_skb类似但是组成只有一个简单这个不做任何事情只是调用kfree_skb只有skb->users 计数器1(缓冲区已经无任何用户时)这个基本函数才会释放一个缓冲区否则只是递减计数器所以如果一个缓冲区三位用户只有三次调用dev_kfree_skbkfree_skb才会释放内存

2-6流程显示释放一个缓冲区所有步骤三十三会看到一个sk_buff结构可以持有一次dst_entry数据结构引用因此sk_buff结构被释放必须调用dst_release 递减相关dst_entry 数据结构引用计数

destructor函数指针已经初始化就会在这里调用

2-5 看起来是一个简单场景一个sk_buff数据结构另一个实际存储数据内存相关联然而如图2-5所示数据区块底端skb_shared_info数据结构可以持有一些指向其他内存片段指针参见二十一实例kfree_skb 也会释放这些片段持有内存最后sk_buff数据结构返回skbuff_head_cache缓存

数据预留对齐:skb_reserve, skb_put, skb_push以及skb_pull

skb_reserve缓冲区头部预留一些空间通常允许插入一个报头或者强迫数据对齐某个边界函数移动标记有效载荷开端指针data尾端指针tail2-4 显示调用skb_reserve 之后结果缓冲区分配之后通常马上就会调用函数此时datatail仍然相同

如果你看一下几种Ethernet驱动程序之一函数你会发现它们任何数据存储分配缓冲区之前都会使用下列命令

递减skb引用计数

skb->users

|

skb引用计数0 返回

skb列表中

打印警告信息(可能是bug)

skb->destructor 已经初始化了吗

是 执行解析函数 skb_releaese_data

skb克隆 释放主要缓冲区以及任何片段

dataref 引用计数0

skb返回缓存

2-6 kfree_skb 函数

skb_reserve(skb, 2) //IP对齐16字节地址边界

由于知道要把一个带有14字节头Ethernet 拷贝到缓冲区参数2使缓冲区移动2字节这样IP报头就可以缓冲区开始按照16字节边界对齐紧接Ethernet报头之后如图2-7所示

(a)

struct sk_buff

len = 0

head

data

tail

end

(b)

struct sk_buff

len = 0;

head

data

tail

end

...

(c)

struct sk_buff

len=L

head

data

tail

end

填充区域 2

Ethernet

报头 14

IP报头

IP 有效载荷

2-7 skb_reserve之前bskb_reserve 之后C拷贝缓冲区之后

2-8所示数据传输期间相反方向使用skb_reserve实力

(a)

struct sk_buff

len = 0

head

data

tail

end

(b)

struct sk_buff

len = 0;

head

data

tail

end

(c)

len = L1

head

data

tail

end IP有效载荷

2-8 缓冲区穿过协议栈TCP向下链路层

1 TCP请求传输一些数据会根据一些准则TCP MSS .支持分散-聚集IO分配一个缓冲区

2 TCP会在缓冲区头部预留足够空间容纳所有层TCP 报头参数MAX_TCP_HEADER所有报头总和计算要考虑最坏情况因为TCP不知道传输接口类型, 因此每个分层预留最大可能报头甚至考虑多个IP报头可能性IP-over-IP通道就可能多个报头

3 TCP有效载荷拷贝缓冲区注意2-8只是一个例子而已TCP有效载荷可能不同方式组织如果可以作为多个片段存储二十一我们看到片段缓冲形式

4 TCP添加报头

5 TCP缓冲区传给IPIP同样添加报头

6 IPIP风暴传给邻居层邻居层链路层报头添加进来

注意当缓冲区往下传播经过网络协议栈每个协议都会吧skb-》data传下并将其报头拷贝进来然后更新skb->len 这一都是我们2-4所看到函数完成

注意skb_reserve函数没有其他任何东西移入数据缓冲区只是更新2-4所示两个指针而已

static inline void skb_reserve(struct sk_buff *skb, unsigned int len)

{

skb->data += len;

skb->tail+=len;

}

skb_push 会把一个数据块添加到缓冲区开端skb->put会把一个数据块添加到缓冲区尾端skb_reserve一样这些函数并没有真的数据添加缓冲区只是简单移动指向头尾指针数据应该有其他函数明确拷贝进来skb_pull通过head指针向前移动一个数据块缓冲区头部删除

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值