socket buffer套接字缓存

最近公司在开发机器人与服务器调度端的通信时需要使用socket,因此找到了该文章作为深刻理解socket内部运作。

Linux网络核心数据结构是套接字缓存(socket buffer),简称skb。它代表一个要发送或处理的报文,并贯穿于整个协议栈。

1、    套接字缓存
skb由两部分组成:
(1)    报文数据:它保存了实际在网络中传输的数据;
(2)    管理数据:供内核处理报文的额外数据,这些数据构成了协议之间交换的控制信息。
当应用程序向一个socket传输数据之后,该socket将创建相应的套接字缓存,并将用户数据拷贝到缓存中。当报文在各协议层传达输的过程中,每一导的报文头将插入到用户数据之前。skb为报文头申请了足够的空间,所以避免了由于插入报文头而对报文进行多次拷贝。用户数据只拷贝了两次:一是从用户空间拷贝到内核;二是报文数据从内核传送到网络适配器。
1.1、sk_buff

套接字缓存结构:


[cpp] view plaincopy
  1. struct sk_buff {  
  2.     /* These two members must be first. */  
  3.     struct sk_buff        *next;    
  4.     struct sk_buff        *prev;  
  5.   
  6.     struct sk_buff_head    *list;    
  7.     struct sock        *sk;          //指向创建报文的socket  
  8.     struct timeval        stamp;  //此报文收到时的时间  
  9.     struct net_device    *dev;          //收到此报文的网络设备   
  10.     struct net_device    *input_dev;  
  11.     struct net_device    *real_dev;  
  12.   
  13.     //TCP报头  
  14.     union {    
  15.         struct tcphdr    *th;   //tcp头  
  16.         struct udphdr    *uh;  //udp头  
  17.         struct icmphdr    *icmph;  
  18.         struct igmphdr    *igmph;  
  19.         struct iphdr    *ipiph;  
  20.         struct ipv6hdr    *ipv6h;  
  21.         unsigned char    *raw;  
  22.     } h;  
  23.     //IP报头  
  24.     union {  
  25.         struct iphdr    *iph;  
  26.         struct ipv6hdr    *ipv6h;  
  27.         struct arphdr    *arph;  
  28.         unsigned char    *raw;  
  29.     } nh;  
  30.     //链路层帧头  
  31.     union {  
  32.           unsigned char     *raw;  
  33.     } mac;  
  34.   
  35.     struct  dst_entry    *dst;  //此报文的路由,路由确定后赋此值  
  36.     struct    sec_path    *sp;  
  37.   
  38.     /* 
  39.      * This is the control buffer. It is free to use for every 
  40.      * layer. Please put your private variables there. If you 
  41.      * want to keep them across layers you have to do a skb_clone() 
  42.      * first. This is owned by whoever has the skb queued ATM. 
  43.      */  
  44.     char            cb[40];  
  45.       
  46.     //此报文的长度,这是指网络报文在不同协议层中的长度,包括头部和数据。在协议栈的不同层,这个长度是不同的。   
  47.     unsigned int        len,  
  48.                 data_len,  
  49.                 mac_len,  
  50.                 csum;  
  51.     unsigned char        local_df,  
  52.                 cloned,  
  53.                 pkt_type, //网络报文的类型,常见的有PACKET_HOST,代表发给本机的报文;还有PACKET_OUTGOING,代表本机发出的报文。   
  54.                 ip_summed;  
  55.     __u32            priority;  
  56.        
  57.     unsigned short        protocol,//链路层协议  
  58.                 security;  
  59.   
  60.     void            (*destructor)(struct sk_buff *skb);  
  61. #ifdef CONFIG_NETFILTER  
  62.         unsigned long        nfmark;  
  63.     __u32            nfcache;  
  64.     __u32            nfctinfo;  
  65.     struct nf_conntrack    *nfct;  
  66. #ifdef CONFIG_NETFILTER_DEBUG  
  67.         unsigned int        nf_debug;  
  68. #endif  
  69. #ifdef CONFIG_BRIDGE_NETFILTER  
  70.     struct nf_bridge_info    *nf_bridge;  
  71. #endif  
  72. #endif /* CONFIG_NETFILTER */  
  73. #if defined(CONFIG_HIPPI)  
  74.     union {  
  75.         __u32        ifield;  
  76.     } private;  
  77. #endif  
  78. #ifdef CONFIG_NET_SCHED  
  79.        __u32            tc_index;        /* traffic control index */  
  80. #ifdef CONFIG_NET_CLS_ACT  
  81.     __u32           tc_verd;               /* traffic control verdict */  
  82.     __u32           tc_classid;            /* traffic control classid */  
  83. #endif  
  84.   
  85. #endif  
  86.   
  87.   
  88.     /* These elements must be at the end, see alloc_skb() for details.  */  
  89.   
  90.        //此报文存储区的长度,这个长度是16字节对齐的,一般要比报文的长度大  
  91.     unsigned int        truesize;  
  92.     atomic_t        users;  
  93.     /*head和end指向报文数据的整个单元.head与data之间的空间称为headroom,tail与end之间的空间称为tailroom. 
  94.     */  
  95.     unsigned char        *head,  
  96.                 *data,  
  97.                 *tail,  
  98.                 *end;  
  99. };  
1.2、与sk_buff相关的函数
与sk_buff相关的函数涉及到网络报文存储结构和控制结构的分配、复制、释放,以及控制结构里的各指针的操作,还有各种标志的检查。重要的函数说明如下: 

struct sk_buff *alloc_skb(unsigned int size,int gfp_mask
分配大小为size的存储空间存放网络报文,同时分配它的控制结构。size的值是16字节对齐的,gfp_mask是内存分配的优先级。常见的内存分配优先级有GFP_ATOMIC,代表分配过程不能被中断,一般用于中断上下文中分配内存;GFP_KERNEL,代表分配过程可以被中断,相应的分配请求被放到等待队列中。分配成功之后,因为还没有存放具体的网络报文,所以sk_buff的 data,tail指针都指向存储空间的起始地址,len的大小为0,而且 is_clone和cloned两个标记的值都是0。 

struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask
从控制结构skb中 clone出一个新的控制结构,它们都指向同一个网络报文。clone成功之后,将新的控制结构和原来的控制结构的 is_clone,cloned两个标记都置位。同时还增加网络报文的引用计数(这个引用计数存放在存储空间的结束地址的内存中,由函数atomic_t *skb_datarefp(struct sk_buff *skb)访问,引用计数记录了这个存储空间有多少个控制结构)。由于存在多个控制结构指向同一个存储空间的情况,所以在修改存储空间里面的内容时,先要确定这个存储空间的引用计数为1,或者用下面的拷贝函数复制一个新的存储空间,然后才可以修改它里面的内容。 

struct sk_buff *skb_copy(struct sk_buff *skb, int gfp_mask
复制控制结构skb和它所指的存储空间的内容。复制成功之后,新的控制结构和存储空间与原来的控制结构和存储空间相对独立。所以新的控制结构里的is_clone,cloned两个标记都是0,而且新的存储空间的引用计数是1。
 
void kfree_skb(struct sk_buff *skb)
释放控制结构skb和它所指的存储空间。由于一个存储空间可以有多个控制结构,所以只有在存储空间的引用计数为1的情况下才释放存储空间,一般情况下,只释放控制结构skb。 

unsigned char *skb_put(struct sk_buff *skb, unsigned int len
将tail指针下移,并增加skb的 len值。data和 tail之间的空间就是可以存放网络报文的空间。这个操作增加了可以存储网络报文的空间,但是增加不能使tail的值大于end的值,skb的 len值大于truesize的值。 

unsigned char *skb_push(struct sk_buff *skb, unsigned int len
将data指针上移,并增加skb的 len值。这个操作在存储空间的头部增加了一段可以存储网络报文的空间,上一个操作在存储空间的尾部增加了一段可以存储网络报文的空间。但是增加不能使data的值小于head的值,skb的 len值大于truesize的值。 

unsigned char * skb_pull(struct sk_buff *skb, unsigned int len
将data指针下移,并减小skb的 len值。这个操作使data指针指向下一层网络报文的头部。 

void skb_reserve(struct sk_buff *skb, unsigned int len
将data指针和tail指针同时下移。这个操作在存储空间的头部预留 len长度的空隙。
 
void skb_trim(struct sk_buff *skb, unsigned int len
将网络报文的长度缩减到 len。这个操作丢弃了网络报文尾部的填充值。 

int skb_cloned(struct sk_buff *skb
判断skb是否是一个 clone的控制结构。如果是clone的,它的cloned标记是1,而且它指向的存储空间的引用计数大于1。

2、    套接字缓存队列(Socket-Buffer Queues)
2.1、sk_buff_head
在网络协议栈的实现中,有时需要把许多网络报文放到一个队列中做异步处
理。LINUX 为此定义了相关的数据结构 sk_buff_head。这是一个双向链表的
头,它把sk_buff链接成一个双向链表。


 
[cpp] view plaincopy
  1. //套接字缓存队列头  
  2. struct sk_buff_head {  
  3.     /* These two members must be first. */  
  4.     struct sk_buff    *next;  
  5.     struct sk_buff    *prev;  
  6.   
  7.     __u32        qlen; //队列的长度,即队列中报文的数量  
  8.     spinlock_t    lock;  
  9. };  
2.2、与 sk_buff_head相关的函数
void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk
将newsk加到链表 list的头部。 

void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
将newsk加到链表 list的尾部。 

struct sk_buff *skb_dequeue(struct sk_buff_head *list
从链表 list的头部取下一个 sk_buff。 

struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list
从链表 list的尾部取下一个 sk_buff。
 
skb_insert(struct sk_buff *old, struct sk_buff *newsk
将newsk加到old所在的链表上,并且 newsk在old的前面。
 
void skb_append(struct sk_buff *old, struct sk_buff *newsk
将newsk加到old所在的链表上,并且 newsk在old的后面。
 
void skb_unlink(struct sk_buff *skb
将skb从它所在的链表上取下。 
以上的链表操作都是先关中断的。这在中断上下文中是不需要的,所以另外有一套与上面函数同名但是有前缀“__”的函数供运行在中断上下文中的函数调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463752.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LAMP 系统性能调优,第 3 部分: MySQL 服务器调优(转)

关于 MySQL 调优 有 3 种方法可以加快 MySQL 服务器的运行速度,效率从低到高依次为: 替换有问题的硬件。对 MySQL 进程的设置进行调优。对查询进行优化。迁移到 DB2? 您正在寻找一种干净利落、无成本的方法用来从 MySQL 迁移到 IBM? DB2? 吗&#xf…

圆梦,手写了个操作系统

大家好,我是发哥。我不止一次在公众号上强调学习操作系统的重要性。至于学习的方法,无外乎看书、看视频、看源码等等。也有推荐过跟着老师一起手写操作系统,但很少有学习方法能同时兼顾以下三点:1、Linux内核2、Windows内核3、自己…

安卓打包apk

打apk包的环境依赖 1.jdk 2.sdk 3.ndk 打apk包的工具 gradle mkdir /usr/local/Android cd /usr/local/Android mkdir sdk gradle ndk 1.jdk安装 略 2.sdk安装 https://www.androiddevtools.cn/下载地址 cd /usr/local/Android/sdk wget https://dl.google.com/android/andro…

你知道怎么衡量硬件设备的算力吗?

前几天在知乎上看到有知友提问,什么是 GPU 算力。当时简单回答了一下,今天有空,在这里详细谈谈算力。算力也是做高性能计算的核心概念和指标。设备算力分为两部分,其一是设备,其二是算力。设备主要是指 CPU、GPU、DSP、…

Python爬虫入门教程 22-100 CSDN学院课程数据抓取

1. CSDN学院课程数据-写在前面 今天又要抓取一个网站了,选择恐惧症使得我不知道该拿谁下手,找来找去,算了,还是抓取CSDN学院吧,CSDN学院的网站为 https://edu.csdn.net/courses 我看了一下这个网址,课程数量…

UML类图解义 (来自《大话设计模式》)

为什么80%的码农都做不了架构师?>>> 小菜:“对了,我时常在一些技术书中看到这些类图表示,简单的还看得懂,有些标记我很容易混淆。要不你给我讲讲吧。” 大鸟:“这个其实多看多用就熟悉了。我给…

易写易库(EXEK)玩“花”儿之三:命令有图标支持库,附图

释题:如果您认为这个“花”儿,属于之前第一个“花”儿的变种,易语言写支持库也能玩出“花”儿来(易写易库(EXEK)进展5),我也不反对。 在开始正文之前,我要首先回答我之前提出的两个问题&#xf…

您好,有什么嵌入式书籍推荐的?

回答下这个后台的留言-----比较推荐下面这个仓库里面的内容!https://github.com/ZhongYi-LinuxDriverDev/CS-EmbeddedLinux-Book#%E5%85%A8%E9%83%A8%E6%B1%87%E6%80%BB

VS2017打开低版本的VS MVC架构的项目的时候需要修改的地方

1、需要修改的是.sln文件,即将里面的 Version改为12,其中的VS的版本改为2017 2、项目中后缀名为 .csproj中的代码改一下: 转载于:https://www.cnblogs.com/zhijianhao/p/10253572.html

从外部的js文件中获取ASPX页面的控件ClientID(get control reference from external javascript)...

前言 当使用MasterPage、UserControl等容器时,为了避免控件的重复命名,asp.net会自动将容器中的控件生成一个ClientID(Control Tree中的可生成,否则不会生成)。 例如:ContentPlaceHolder1中的Button1默认情…

可怕!CPU暗藏了这些未公开的指令!

我们平时编程写的高级语言,都是经过编译器编译以后,变成了CPU可以执行的机器指令:而CPU能支持的指令,都在它的指令集里面了。很久以来,我都在思考一个问题:CPU有没有未公开的指令?或者说&#x…

A star算法优化二

本文目的是对A*寻路算法所生成的路径进行一些人性化的调整,使其看起来不至于太机械化。关于A*算法的原理与实现,读者可以阅读其他资料,这里不再详细阐述。 如何写估价函数A*寻路算法本质上是一个有方向性的广度优先搜索算法,它使用…

CentOS下python-mysqldb安装

CentOS下python-mysqldb安装日期:2011-04-17 | 来源:未知 | 作者:redice | 869 人围观 | 1 人鼓掌了!鲲鹏Web数据抓取 - 专业Web数据采集服务提供者(1)py…

I2C总线接上拉电阻的原因

I2C为什么要接上拉电阻?因为它是开漏输出。为什么是开漏输出?I2C协议支持多个主设备与多个从设备在一条总线上,如果不用开漏输出,而用推挽输出,会出现主设备之间短路的情况。所以总线一般会使用开漏输出。为什么要接上…

解决循环引用--弱引用weak_ptr

循环引用&#xff1a; 引用计数是一种便利的内存管理机制&#xff0c;但它有一个很大的缺点&#xff0c;那就是不能管理循环引用的对象。一个简单的例子如下&#xff1a; class parent; class children;typedef shared_ptr<parent> parent_ptr; typedef shared_ptr<ch…

第九章 虚拟内存

物理地址和虚拟地址&#xff1a; 计算机的主存被组织成一个由M个连续的字节大小的单元组成的数组。每个字节都有一个唯一的物理地址&#xff08;PA&#xff09;。第一个字节地址为0&#xff0c;接下来为1&#xff0c;再接下来为2&#xff0c;依次类推。CPU访问内存的最自然方式…

Android HandlerThread 总结使用

Android HandlerThread 总结使用转载请标明出处&#xff1a;http://www.cnblogs.com/zhaoyanjun/p/6062880.html本文出自【赵彦军的博客】前言以前我在 【Android Handler、Loop 的简单使用】 介绍了子线程和子线程之间的通信。很明显的一点就是&#xff0c;我们要在子线程中调…

python 文件操作练习

1. 文件a.txt内容&#xff1a;每一行内容分别为商品名字&#xff0c;价钱&#xff0c;个数。 apple 10 3 tesla 100000 1 mac 3000 2 lenovo 30000 3 chicken 10 3 通过代码&#xff0c;将其构建成这种数据类型&#xff1a;[{name:apple,price:10,amount:3},{name:tesla,price:…

微软发布Enterprise Library 4.1和Unity 1.2

说明 微软模式与实践团队今天发布了Enterprise Library 4.1和Unity 1.2版本&#xff0c;这次发布的主要新特性如下&#xff1a; 1. 支持Visual Studio 2008 SP1 2. Unity应用程序块中加入了拦截机制 3. 性能提升 4. 配置工具的可用性提升 5. Bugs修复。 在Unity 1.2中有如下几点…

简易的波形折叠电路

01 波形折叠一、背景介绍今天在 Youtube 上看到 UP 主 Neukolln 展示了一款非常简单波形折叠电路。那么什么是波形折叠电路&#xff1f;它有什么用处&#xff1f;1、什么是波形折叠&#xff1f;通常情况下&#xff0c;信号在放大中会产生“饱和失真”&#xff0c;这是由于放大器…