• 3.4.4 数据预留和对齐(skb_reserve, skb_push, skb_put, skb_pull)


    转自:http://book.51cto.com/art/201206/345043.htm

    《Linux内核源码剖析:TCP/IP实现》本书详细论述了Linux内核2.6.20版本中TCP/IP的实现。书中给出了大量的源代码,通过对源代码的详细注释,帮助读者掌握TCP/IP的实现。本节为大家介绍数据预留和对齐。

    AD:51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验

    3.4.4  数据预留和对齐

    数据预留和对齐主要由skb_reserve()、skb_put()、skb_push()以及skb_pull()这几个函数来完成。

    1.skb_reserve()

    skb_reserve()在数据缓存区头部预留一定的空间,通常被用来在数据缓存区中插入协议首部或者在某个边界上对齐。它并没有把数据移出或移入数据缓存区,而只是简单地更新了数据缓存区的两个指针-分别指向负载起始和结尾的data和tail指针,图3-15 展示了调用skb_reserve()前后这两个指针的变化。

    请注意:skb_reserve()只能用于空的SKB,通常会在分配SKB之后就调用该函数,此时data和tail指针还一同指向数据区的起始位置,如图3-15a所示。例如,某个以太网设备驱动的接收函数,在分配SKB之后,向数据缓存区填充数据之前,会有这样的一条语句skb_reserve(skb, 2),这是因为以太网头长度为14B,再加上2B就正好16字节边界对齐,所以大多数以太网设备都会在数据包之前保留2B。

    当SKB在协议栈中向下传递时,每一层协议都把skb->data指针向上移动,然后复制本层首部,同时更新skb->len。这些操作都使用图3-15 中所示的函数完成。

     
    图3-15  在接收过程中使用skb_reserve()
    a) 空的SKB  b) 头部预留2个字节  c) 复制以太网帧到SKB

    2.skb_push()

    skb_push()在数据缓存区的前头加入一块数据,与skb_reserve()类似,也并没有真正向数据缓存区中添加数据,而只是移动数据缓存区的头指针data和尾指针tail。数据由其他函数复制到数据缓存区中。

    函数执行步骤如下:

    1)当TCP发送数据时,会根据一些条件,如TCP最大分段长度MSS、是否支持聚合分散I/O等,分配一个SKB。

    2)TCP需在数据缓存区的头部预留足够的空间,用来填充各层首部。MAX_TCP_HEADER是各层首部长度的总和,它考虑了最坏的情况:由于TCP层不知道将要用哪个接口发送包,它为每一层预留了最大的首部长度,甚至还考虑了出现多个IP首部的可能性,因为在内核编译支持IP over IP的情况下,会遇到多个IP首部。

    3)把TCP负载复制到数据缓存区。需要注意的是,图3-16 只是一个例子,TCP负载可能会被组织成其他形式,例如分片,在后续章节中将会看到一个分片的数据缓存区是什么样的。

     
    图3-16  TCP层向链路层传递时数据的填充过程
    a) 空的SKB  b) 在SKB的头部预留足够的空间  c) 复制TCP数据  
    d) 添加TCP首部  e) 添加IP首部  f) 添加以太网帧首部

    4)TCP层添加TCP首部。

    5)SKB传递到IP层,IP层为数据包添加IP首部。

    6)SKB传递到链路层,链路层为数据包添加链路层首部。

    3.skb_put()

    skb_put()修改指向数据区末尾的指针tail,使之往下移len字节,即使数据区向下扩大len字节,并更新数据区长度len。调用skb_put()前后,SKB结构变化如图3-17所示。

     
    图3-17  skb_put()示意
    a) 调用前  b) 调用后

    4.skb_pull()

    skb_pull()通过将data指针往下移动,在数据区首部忽略len字节长度的数据,通常用于接收到数据包后在各层间由下往上传递时,上层忽略下层的首部。调用skb_pull()前后,SKB结构变化如图3-18所示。

     
    图3-18  skb_pull()示意
    a) 调用前  b) 调用后

     

  • 相关阅读:
    Easyui-datagrid显示时间的格式化代码
    JSP页面与JSP页面之间传输参数出现中文乱码的解决方案
    SpringMVC中在web.xml中添加中文过滤器的写法
    SpringMVC的实现过程
    BeanFactory 和 ApplicationContext的区别
    Spring中的IoC(控制反转)具体是什么东西
    Spring/AOP框架, 以及使用注解
    面向切面编程
    Spring的属性注入, byName和byType还有注入List属性
    反射, getClass(), 和something.class以及类型类(转)
  • 原文地址:https://www.cnblogs.com/x_wukong/p/6048136.html
Copyright © 2020-2023  润新知