分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
可以说sk_buff结构体是Linux网络协议栈的核心中的核心,几乎所有的操作都是围绕sk_buff这个结构体进行的,它的重要性和BSD的mbuf类似(看过《
TCP/IP详解 卷2》的都知道),那么sk_buff是什么呢?
sk_buff就是网络数据包本身以及针对它的操作元数据。
想要理解sk_buff,最简单的方式就是凭着自己对网络协议栈的理解封装一个直到以太层的数据帧并且成功发送出去,个人认为这比看代码/看文档或者在网上搜资料强多了。当然,网上已经有了大量的这方面的文章,但是我认为很多都太复杂了,它们都细化到了sk_buff结构体的每一个指针字段,并且还都画出了图,但一般都逃不过《 深入理解Linux网络技术内幕》这本书的圈子。试想,如果以后内核版本升级了,字段新增了或者名字变了,怎么办?这些文章包括那本经典的《 ULN》还能有帮助吗?
因此,本文绝不深入到sk_buff的细节,但是相信这种简单的方式可以让自己在多年以后早已忘了什么是Linux协议栈的情况下,瞬间理解Linux是如何通过sk_buff封装数据包的。我们从网络的分层模型开始。
1.分配一个skb结构体
2.分配数据包的数据区
3.在skb数据区定位应用层起始位置
4.拷贝数据到应用层(假设应用层协议没有在socket接口之上被封装)
5.在skb数据区定位传输层起始位置
6.设置传输层头部字段
7.在skb数据区定位IP层起始位置
8.设置IP层头部字段
9.在skb数据区定位以太层起始位置
10.设置以太头部字段
可以看出基本的模式,即“定位/设置”两步骤操作,有点区别的是应用层操作,这是因为应用层的操作一般都是在socket接口之上完成的。但是既然本文讲述的是skb的通用操作,就不再区分这个了。
sk_buff就是网络数据包本身以及针对它的操作元数据。
想要理解sk_buff,最简单的方式就是凭着自己对网络协议栈的理解封装一个直到以太层的数据帧并且成功发送出去,个人认为这比看代码/看文档或者在网上搜资料强多了。当然,网上已经有了大量的这方面的文章,但是我认为很多都太复杂了,它们都细化到了sk_buff结构体的每一个指针字段,并且还都画出了图,但一般都逃不过《 深入理解Linux网络技术内幕》这本书的圈子。试想,如果以后内核版本升级了,字段新增了或者名字变了,怎么办?这些文章包括那本经典的《 ULN》还能有帮助吗?
因此,本文绝不深入到sk_buff的细节,但是相信这种简单的方式可以让自己在多年以后早已忘了什么是Linux协议栈的情况下,瞬间理解Linux是如何通过sk_buff封装数据包的。我们从网络的分层模型开始。
网络分层模型
这是一切的本质。网络被设计成分层的,所以网络的操作就可以称作一个“栈”,这就是网络协议栈的名称的由来。在具体的操作上,数据包最终形成的过程就是一层一层封装的过程,在栈上形成一段连续的数据,我们可以称作是一层一层的push操作。同样的,数据包的解封装的过程,则可以认为是一层一层的pop操作。sk_buff的操作
要想形成一个最终的数据包,即以太帧(不考虑其它的链路层)。要进行以下的操作:1.分配一个skb结构体
2.分配数据包的数据区
3.在skb数据区定位应用层起始位置
4.拷贝数据到应用层(假设应用层协议没有在socket接口之上被封装)
5.在skb数据区定位传输层起始位置
6.设置传输层头部字段
7.在skb数据区定位IP层起始位置
8.设置IP层头部字段
9.在skb数据区定位以太层起始位置
10.设置以太头部字段
可以看出基本的模式,即“定位/设置”两步骤操作,有点区别的是应用层操作,这是因为应用层的操作一般都是在socket接口之上完成的。但是既然本文讲述的是skb的通用操作,就不再区分这个了。
skb的核心操作
在上面一小节,我们展示了skb的封装逻辑,但是具体到接口层面,就涉及到了skb的核心操作。1.分配skb
这个是由alloc_skb完成的,完成同一任务的接口形成一个接口族,但是alloc_skb是最基本的接口。该alloc_skb接口完成两件事,即分配skb结构体以及skb数据包缓冲区,设置初始值。size参数表示sk