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协议栈的轮廓有一个大概的印象了,能够对整体有所把握. ...
随机推荐
- SQLSERVER中NULL位图的作用
SQLSERVER中NULL位图的作用 首先感谢宋沄剑提供的文章和sqlskill网站:www.sqlskills.com,看下面文章之前请先看一下下面两篇文章 SQL Server误区30日谈-Da ...
- express全局安装后无法通过require使用
今天入门了一下express,首先安装依赖. npm install express -g; npm install body-parser -g; npm install cookie-parser ...
- Python初学者之网络爬虫
声明:本文内容和涉及到的代码仅限于个人学习,任何人不得作为商业用途. 本文将介绍我最近在学习Python过程中写的一个爬虫程序,将力争做到不需要有任何Python基础的程序员都能读懂.读者也可以先跳到 ...
- XSS原理
跨站脚本攻击(Cross-Site Scripting),是一种网站应用程序的安全漏洞,是代码注入攻击的一种. XSS的种类: 反射型XSS: 非持久型XSS(需要自行触发,输入-输出). ...
- 阿里云服务器的坑=====部署EF+MVC
异常处理汇总 ~ 修正果带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4599258.html 先参考:http://www.cnblogs.com/dun ...
- h5应用缓存及收藏时Icon显示
h5应用实现离线缓存,加载后,断网仍然可以继续使用. 一.需求 转行做h5,目前做赛道游戏,动手做了个赛道编辑器web版的,由于web版需要开启服务器才能使用,策划要想回家使用就要发布到外网服务器了, ...
- Oracle架构设计01:表空间的管理维护规范
Oracle数据库的表空间管理可以说是非常简单和基础的一项维护工作,但是越简单的事情就越要制定统一的规范,这样数据库的各项管理工作才会愈加的简单高效. 那么接下来,问题来了.. Q1:当我们接手一个新 ...
- 浅谈css的伪元素::after和::before
css中的::after和::before已经被大量地使用在我们日常开发中了,使用他们可以使我们的文档结构更加简洁.但是很多人对::after和::before仍不是特别了解,究竟他们是做什么的?如何 ...
- Android重构与设计之路,从整理提示弹窗(SmartAlertPop)开始
封装一个独立弹窗Module,这里的弹窗包括普通的Dialog方式弹框和WindowManager方式弹窗.提供一种管理项目里面弹窗的方案,便于后期修改和维护. 首先描述一个在大项目中普遍存在的一个现 ...
- 使用OWIN作为WebAPI的宿主
前言 好吧,也没什么好说的,就是个技术的总结,直接生成MVC的项目,感觉好重,虽然各种东西很全 ...也许我是处女座? - -, OWIN呃,这里我就不解释了,自己也是一知半解,可以参考 Open W ...