无论何时,一个激活的监听socket接收一个连入的TCP连接请求,TCP都要建立一个新的 sock 结构来描述它 。最终接收时,这个 sock 结构将成为TCP连接的底层 。它也复制包含连接请求的 sk_buff,并将它放到监听 sock 结构的 receive_queue 中排队 。复制的 sk_buff 包含一个指向新建立的 sock 结构的指针 。
10.4.5接收连接请求
UDP不支持连接的概念,接收INET socket连接请求只适用于TCP协议,一个监听socket接收操作从原始的监听socket中复制新的socket结构 。接收操作透过支持的协议层,本例是INET,来接收任何连入连接请求 。如果下层协议,如UDP,不支持连接,INET协议层接收操作将失败 。否则接收操作透过真实协议层,本例是TCP 。接收操作可以是阻塞或非阻塞 。在非阻塞情况下,如果没有连入连接可接收,则接收操作失败,新建的socket 结构被废弃 。在阻塞情况下,网络应用程序执行接收操作将加上一个等待队列并将之挂起,直到接收到TCP连接请求 。当接收一个连接请求后,包含请求的 sk_buff 被废弃,并且 sock 数据结构返回到INET socket层,在那与一个新的更早建立的socket结构连接 。新socket文件描述符(fd)号返回给网络应用程序,然后,应用程序就能在socket操作中将这一文件描述符用于新建立的INET BSD socket 。
10.5IP层
10.5.1Socket 缓存
每一层协议用另外层提供的服务,这样使用多层网络协议会有一个问题:每个协议都要在传送数据时都要 加上协议头和协议尾,而数据到达时又要将之去掉 。这样,在不同的协议间要有数据缓存,每一层需要知道特 定协议的头和尾放在哪个位置 。一个解决办法就是在每一层中都拷贝缓存,但这样做效率就很低 。Linux用 socket缓存或者说 sk_buffs 来在协议层与网络设备驱动之间交换数据 。sk_buffs 包括指针和字段长度,这样每 个协议层就可以通过标准的函数或“方法”来操作应用程序数据 。
图 10.4: Socket 缓存 (sk_buff)
图10.4 显示了 sk_buff 数据结构;每个 sk_buff 有一个数据块与之相连 。sk_buff 有四个指针,这些指针 用来操作和管理socket缓存的数据:
head
指向内存中数据区的开头 。这一指针在 sk_buff 和其相关的数据块分配时就固定了 。
data
指向当前协议数据的开头 。这一指针是随当前拥有 sk_buff 的是哪个协议层而变化的 。
tail
指向当前协议数据的结尾 。同样,这一指针也是随当前拥有 sk_buff 的是哪个协议层而变化的 。
end
指向内存中数据区的结尾 。这一指针在 sk_buff 和其相关的数据块分配时固定 。
len 和 truesize 这两个字段分别用来描述当前协议包长度和数据缓存总体长度 。sk_buff 处理代码提供标准的操作来向应用程序增加和移除协议头和协议尾 。这就可以安全地操作 sk_buff 中的 data , tail 和 len 字段 。
push
它把 data 指针指向数据区的开始并增加 len。用于在要传输的数据开始处增加协议头 。
pull
它把 data 指针从数据区的开始处移到数据区的结尾处,并减小 len。用于在已接收的数据开始处移除协议头 。
put
它把 tail 指针指向数据区的结尾处,并增加 len。用于在要传输的数据结尾处增加数据或协议信息 。
trim
它把 tail 指针指向数据区的开始处,并减小 len。用于在已接收的数据尾移除数据或协议信息 。
sk_buff 结构还包含了用于一些指针,用于在处理过程中存入 sk_buff 的双连接环路列表 。通用sk_buff例 程可以将 sk_buff 加入到这些列表的前面或后面,也可以删除它们 。
推荐阅读
- Linux 核心--10.文件系统
- 诺基亚将在更多产品上采用Linux操作系统
- 蛤蟆皮的功效与作用 蛤蟆皮的功效
- Linux 核心--7.PCI设备
- Linux 核心--8.中断与中断处理
- 椰子汤的功效与作用 椰子汤有什么功效
- Linux操作系统如何限制SSH密码尝试次数
- 微软公司对Linux操作系统使出的各种杀招
- Linux 核心--4.内存管理
- 以Linux做路由器的问题