Linux2.6内核协议栈系列--TCP协议2.接收
1.排队机制
接收输入TCP报文时,有三个队列:
● 待处理队列
● 预排队队列
● 接收队列
接收队列包含了处理过的TCP数据段,也就是说,去除了全部的协议头,正准备将数据复制到用户应用程序。接收队列包含了所有按顺序接收的数据段,在其他两个队列中的TCP数据段则需要进一步处理。
TCP报文首先由tcp_v4_rcv()进行处理。该函数要决定是否需要处理报文或者在待处理队列和预排队队列中排队。
/* 传输层报文处理入口 */
int tcp_v4_rcv(struct sk_buff *skb)
{
...
/*首先获取一个套接字旋转锁,当进入该例程时,要禁用下半部功能,因为该
例程是从NET SoftIRQ中断调用的。*/
bh_lock_sock(sk);/* 在软中断中对套接口加锁 */
ret = 0;
/* 如果进程没有访问传输控制块,则进行正常接收 */
/*接着检查套接字是否处于使用状态。当有人在使用该套接字时,(sk)->sk_lock.owner
为1.当对套接字执行读、写、修改操作时,套接字就会处于使用状态。*/
if (!sock_owned_by_user(sk)) {
/*调用tcp_prequeue将该TCP报文发往预排队队列。*/
if (!tcp_prequeue(sk, skb))
/*如果无法将TCP排队,就直接处理该数据段。*/
ret = tcp_v4_do_rcv(sk, skb);
} else
/* 将报文添加到后备队列中,待用户进程解锁控制块时处理 */
sk_add_backlog(sk, skb);
bh_unlock_sock(sk);
...
}
2.tcp_rcv_established()的处理
这里不介绍全部处理细节,仅介绍处理和排队机制。首先讨论直接将数据复制到用户缓冲区的可能性。如果不可能,就去除TCP头,将数据段发往接收队列排队。
/* 当连接已经正常建立时,处理接收到的TCP报文 */
int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
struct tcphdr *th, unsigned len)
{
struct tcp_sock *tp = tcp_sk(sk);
...
}
else {/* 有数据负荷 */
int eaten = 0; /* 判断正在接收的段是否可以直接复制到用户空间 */
/* 正在接收的段的序号是否与尚未从内核空间复制到用户空间的段最
前面的序号相等,即接收队列应当是空的 */
/* TCP段中的用户数据长度小于用户空间缓存的剩余可用量 */
if (tp->ucopy.task == current &&
tp->copied_seq == tp->rcv_nxt &&
len - tcp_header_len <= tp->ucopy.len &&
sock_owned_by_user(sk)) {/* 锁被当前进程持有 */
__set_current_state(TASK_RUNNING); /* 将SKB的数据复制到用户缓冲区 */
if (!tcp_copy_to_iovec(sk, skb, tcp_header_len)) { if (tcp_header_len ==
(sizeof(struct tcphdr) +
TCPOLEN_TSTAMP_ALIGNED) &&
tp->rcv_nxt == tp->rcv_wup)/* 更新时间戳 */
tcp_store_ts_recent(tp); tcp_rcv_rtt_measure_ts(tp, skb);/* 更新往返时间 */ __skb_pull(skb, tcp_header_len);
/* 下一个预期接收的段序号 */
/*将tp->rcv_nxt更新为已处理报文的结束序列号。*/
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
NET_INC_STATS_BH(LINUX_MIB_TCPHPHITSTOUSER);
eaten = 1;
}
}
if (!eaten) {
...
/* 移动指针,跳过TCP头部,也就是去除TCP头 */
__skb_pull(skb,tcp_header_len);
/* 将数据包添加到接收队列中缓存起来,等待进程主动读取 */
__skb_queue_tail(&sk->sk_receive_queue, skb);
/* 设置skb的属主为当前套口,更新使用的接收缓存总量及预分配缓存长度 */
sk_stream_set_owner_r(skb, sk);
/* 更新rcv_nxt为该分段的结束序列号 */
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
}
...
return 0;
}
3.
内容太多了,未完待续
Linux2.6内核协议栈系列--TCP协议2.接收的更多相关文章
- Linux2.6内核协议栈系列--TCP协议1.发送
在介绍tcp发送函数之前得先介绍很关键的一个结构sk_buff,在linux中,sk_buff结构代表了一个报文: 然后见发送函数源码,这里不关注硬件支持的分散-聚集: /* sendmsg系统调用在 ...
- 网络编程--使用TCP协议发送接收数据
package com.zhangxueliang.tcp; import java.io.IOException; import java.io.OutputStream; import java. ...
- Linux 内核协议栈之TCP连接关闭
Close行为: 当应用程序在调用close()函数关闭TCP连接时,Linux内核的默认行为是将套接口发送队列里的原有数据(比如之前残留的数据)以及新加入 的数据(比如函数close()产生的FIN ...
- Linux2.6内核进程调度系列--scheduler_tick()函数1.总体思想
参考的是ULK第三版,Linux2.6.11.12内核版本. 调度程序依靠几个函数来完成调度工作,其中最重要的第一个函数是scheduler_tick函数,主要步骤如下: /** * 维持当前最新的t ...
- 结合Wireshark捕获分组深入理解TCP/IP协议栈之TCP协议(TCP报文格式+三次握手实例)
摘要: 本文简单介绍了TCP面向连接理论知识,详细讲述了TCP报文各个字段含义,并从Wireshark俘获分组中选取TCP连接建立相关报文段进行分析. 一.概述 TCP是面向连接的可靠 ...
- Linux2.6内核进程调度系列--scheduler_tick()函数3.更新普通进程的时间片
RT /** * 运行到此,说明进程是普通进程.现在开始更新普通进程的时间片. */ /* 首先递减普通进程的时间片计数器.如果用完,继续执行以下操作 */ if (!--p->time_sli ...
- Linux2.6内核进程调度系列--scheduler_tick()函数2.更新实时进程的时间片
RT /** * 递减当前进程的时间片计数器,并检查是否已经用完时间片. * 由于进程的调度类型不同,函数所执行的操作也有很大差别. */ /* 如果是实时进程,就进一步根据是FIFO还是RR类型的实 ...
- TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现
题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com linu ...
- 渣渣小本求职复习之路每天一博客系列——TCP/IP协议栈(5)
前情回顾:一篇短短的博客明显不能满足TCP和UDP这两个饥渴的汉子,而且还被应用协议占了一小半的篇幅.在昨天结束之后,相信大家都基本对TCP/IP协议栈的轮廓有一个大概的印象了,能够对整体有所把握. ...
随机推荐
- 机器指令翻译成 JavaScript —— No.7 过渡语言
上一篇,我们决定使用 LLVM 来优化程序,并打算用 C 作为输入语言.现在我们来研究一下,将 6502 指令转换成 C 的可行性. 跳转支持 翻译成 C 语言,可比 JS 容易多了.因为 C 支持 ...
- Xamarin开发Android应用打包apk
Visual Studio中用Xamarin开发Android应用,生成apk文件有3种方法 1.debug时,代码目录下bin\Debug中会自动生成调试用***-Signed.apk文件,但是文件 ...
- HTML5 摇一摇加强版之一次失败的探索
最近在看设备传感器的API,当然也少不了研究一下让微信称神的“摇一摇”了.关于“摇一摇”的实现,网上很多资料所以不详细说了,但总是有布局.效果不全等各种问题,所以作为一名资深copypaster,代码 ...
- Nova PhoneGap框架 总结
Nova PhoneGap Framework 是完全针对PhoneGap应用程序量身定做的,在这个框架下开发的应用程序很容易实现高质量的代码,很容易让程序拥有很好的性能和用户体验. 在经历了多个项目 ...
- 自定义Sublime Text的图标
sublime text很赞,windows上最接近mac逼格的轻量编辑器,对于我这样比较喜欢格调的人来说,简直不二之选啊. 美中不足的是,看久了觉得它的图标似乎不是很上心.现在都流行扁平化了而它还停 ...
- linux tree 命令
使用cmder确实是方便了很多,想看命令帮助信息: $ help tree 以图形显示驱动器或路径的文件夹结构. TREE [drive:][path] [/F] [/A] /F 显示每个文件夹中文件 ...
- 解析大型.NET ERP系统 权限模块设计与实现
权限模块是ERP系统的核心模块之一,完善的权限控制机制给系统增色不少.总结我接触过的权限模块,以享读者. 1 权限的简明定义 ERP权限管理用一句简单的话来说就是:谁 能否 做 那些 事. 文句 含义 ...
- Android开发之自定义组件和接口回调
说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...
- PHP的学习--在Atom中使用XDebug(Mac)
之前写过一篇博客<PHP的学习--在sublime中使用XDebug(Ubuntu)>,讲了在Ubuntu系统 sublime 中配置 XDebug,其实配置好之后,我也很少用,原因有两点 ...
- SQL Server 统计信息更新时采样百分比对数据预估准确性的影响
为什么要写统计信息 最近看到园子里有人写统计信息,楼主也来凑热闹. 话说经常做数据库的,尤其是做开发的或者优化的,统计信息造成的性能问题应该说是司空见惯. 当然解决办法也并非一成不变,“一招鲜吃遍天” ...