kernel笔记:TCP参数
本文将介绍网络连接建立的过程、收发包流程,以及其中应用层、tcp层、ip层、设备层和驱动层各层发挥的作用。
应用层
对于使用socket进行网络连接的服务器端程序,我们会先调用socket函数创建一个套接字:
- fd = socket(AF_INET, SOCK_STREAM, 0);
以上指定了连接协议,socket调用返回一个文件句柄,与socket文件对应的inode不在磁盘上,而是存在于内存。
之后我们指定监听的端口、允许与哪些ip建立连接,并调用bind完成端口绑定:
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(PORT);
- server_addr.sin_addr.s_addr = INADDR_ANY;
- bind(fd, (struct sockaddr_in *)&server_addr, sizeof(struct sockaddr_in));
端口作为进程的标识,客户端根据服务器ip和端口号就能找到相应进程。
接着我们调用listen函数,对端口进行监听:
- listen(fd, backlog);
backlog值指定了监听队列的长度,以下内核参数限制了backlog可设定的最大值:
- linux # sysctl -a | grep somaxconn
- net.core.somaxconn = 128
监听端口在listen调用后变为LISTEN状态:
- linux # netstat -antp | grep 9999
- Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
- tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN 8709/server
相应地,客户端调用connect进行连接,tcp三次握手在connect调用返回之前完成:

如果服务器端向客户端发送SYN+ACK后,客户端不返回ACK,则服务器保持半连接(SYN_RECV)状态:
- linux # netstat -np | grep SYN_RECV
- tcp 0 0 0.0.0.0:9999 127.0.0.0.1:5334 SYN_RECV -
若队列中的连接均处于半连接状态,服务器将不能处理正常的请求,syn泛洪攻击(syn flood)就是利用这个特点完成DoS(拒绝服务攻击)。
当连接数超过队列长度backlog时,超出的连接也保持为半连接状态,直到数量达到内核参数tcp_max_syn_backlog值,超出该值的连接请求将被丢弃:
- linux # sysctl -a | grep tcp_max_syn
- net.ipv4.tcp_max_syn_backlog = 1024
accept调用用于处理新到来的连接:
- new_fd = accept(fd, (struct sockaddr*)&client_addr, &sin_size);
其返回一个文件描述符,后续我们可以对该文件描述符调用write、read等操作函数,原监听端口仍处于LISTEN状态:
- linux # netstat -antp | grep 9999
- tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN 8709/server
- tcp 0 0 127.0.0.1:9999 127.0.0.1:52274 ESTABLISHED -
以上为网络连接建立过程中,应用层所做的工作,server端完成了socket创建、端口绑定、端口监听、连接和收发包任务,而client端相对简单,只需包含连接和收发包。
tcp层
内核代码中,tcp_sendmsg是tcp发包的主入口函数,该函数中struct sk_buff结构用于描述一个数据包。
对于超过MTU(maximum transmission unit, 最大传输单元)的数据包,tcp层会对数据包进行拆分,若开启了网口的tcp segmentation offload功能,则拆分工作由网卡完成:
- linux # ethtool -k ether
- Offload parameters for eth1:
- rx-checksumming: on
- tx-checksumming: on
- scatter-gather: on
- tcp segmentation offload: on
以下内核参数是内核为tcp socket预留的用于发送数据包的缓冲区大小,单位为byte:
- linux # sysctl -a | grep tcp_wmem
- net.ipv4.tcp_wmem = 4096 16384 131072
默认的用于包发送的缓冲区大小为16M。
除了用于缓冲收发数据包,对于每个socket,内核还要分配一些数据结构用于保持连接状态,内核对tcp层可使用的内存大小进行了限制:
- linux # sysctl -a | grep tcp_mem
- net.ipv4.tcp_mem = 196608 262144 393216
以上值以页为单位,分别对应最小值、压力值和最大值,并在系统启动、tcp栈初始化时根据内存总量设定。通过proc提供的接口,我们可以查到tcp已用的内存页数:
- linux # cat /proc/net/sockstat
- sockets : used 91
- TCP : inuse 8 orphan 0 tw 11 alloc 13 mem 2
ip层
内核代码中,ip_queue_xmit函数是ip层的主入口函数,注意ip层与tcp层操作的都是同一块内存(sk_buff结构),期间并没有发生数据包相关的内存拷贝。
ip层主要完成查找路由的任务,其根据路由表配置,决定数据包发往哪个网口,另外,该层实现netfilter的功能。
网络设备层
dev_queue_xmit是网络设备层的主入口函数,该层为每个网口维护一条数据包队列,由ip层下发的数据包放入对应网口的队列中。在该层中,数据包不是直接交给网卡,而是先缓冲起来,再通过软中断(NET_TX_SOFTIRQ)调用qdisc_run函数,该函数将数据包进一步交由网卡处理。我们执行ifconfig时,txqueuelen指示了网络设备层中,网口队列的长度。
驱动层
使用不同驱动的网卡,相应的驱动层代码就不一样,这里以e1000网卡为例。e1000_xmit_frame是该层的主入口函数,该层利用环形队列进行数据包管理,由两个指针负责维护环形队列。执行ethtool命令,我们可以查询网口驱动层环形队列长度:
- linux # ethtool -g eth1
- Ring parameters for ether
- Pre-set maximums:
- RX : 511
- RX Mini : 0
- RX Jumbo : 0
- TX : 511
- Current hardware settings:
- RX : 200
- RX Mini : 0
- RX Jumbo : 0
- TX : 511
以上RX与TX分别指示收包队列与发包队列长度,单位为包个数。
网卡接收到数据包时将产生中断,以通知cpu数据包到来的消息,而网卡接收包又非常繁忙,如果每次收发包都向cpu发送硬中断,那cpu将忙于处理网卡中断。
相应的优化方案是NAPI(New API)模式,其关闭网卡硬中断,使网卡不发送中断,而非使cpu不接收网卡中断。在e1000驱动代码中,由e1000_clean函数实现NAPI模式。
不像写文件的过程,磁盘设备层完成内存数据到磁盘拷贝后,会将消息层层上报,这里的网卡驱动层发包后不会往上层发送通知消息。
收包过程
以上为网络发包所需经过的层次结构,以及各层的大体功能,下面我们简单看下收包过程。
网卡接收到数据包后,通知上层,该过程不会发生拷贝,数据包丢给ip层。
内核代码中,ip_rcv是ip层收包的主入口函数,该函数由软中断调用。存放数据包的sk_buff结构包含有目的地ip和端口信息,此时ip层进行检查,如果目的地ip不是本机,则将包丢弃,如果配置了netfilter,则按照配置规则对包进行转发。
tcp_v4_rcv是tcp层收包的接收入口,其调用__inet_lookup_skb函数查到数据包需要往哪个socket传送,之后将数据包放入tcp层收包队列中,如果应用层有read之类的函数调用,队列中的包将被取出。
tcp层收包使用的内存同样有限制:
- linux # sysctl -a | grep rmem
- net.ipv4.tcp_rmem = 4096 16384 131072
kernel笔记:TCP参数的更多相关文章
- 关于高负载服务器Kernel的TCP参数优化
net.ipv4.tcp_mem 内核分配给TCP连接的内存,单位是Page,1 Page = 4096 Bytes,可用命令查看: #getconf PAGESIZE 4096 net.ipv4.t ...
- Windows下tcp参数优化
Windows系统下的TCP参数优化2013-04-25 0 个评论 作者:最初的幸福ever收藏 我要投稿Windows系统下的TCP参数优化 TCP连接的状态与关闭方 ...
- Windows系统下的TCP参数优化
1. TCP连接的状态 首先介绍一下TCP连接建立与关闭过程中的状态.TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用.特定数据包以及超时等,具体状态如下所示: CLOSED:初始状态, ...
- Windows系统下的TCP参数优化(注册表\TCPIP\Parameters)
转自:https://blog.csdn.net/libaineu2004/article/details/49054261 Windows系统下的TCP参数优化 TCP连接的状态与关闭方式及其对 ...
- linux kernel的cmdline参数解析原理分析【转】
转自:https://blog.csdn.net/skyflying2012/article/details/41142801 版权声明:本文为博主kerneler辛苦原创,未经允许不得转载. htt ...
- linux kernel笔记
文章目录 关于linux内核中的__attribute__关键字 Linux kernel启动参数 gdt / ldt PCB 关于linux内核中的__attribute__关键字 part I: ...
- Java套接字Socket编程--TCP参数
在Java的Socket中,主要包含了以下可设置的TCP参数. 属性 说明 默认值 SO_TIMEOUT 对ServerSocket来说表示等待连接的最长空等待时间; 对Socket来说表示读数据最长 ...
- linux下如何配置TCP参数设置详解
设置tcp参数一定要小心谨慎,轻易不要更改线上环境,我贴一下我们线上环境中,sysctl.conf的内容,见文章底部 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tc ...
- tcp/ip学习笔记-TCP
tcp/ip学习笔记-TCP 彭会锋 报文发送采用的是tcp_output函数,
随机推荐
- DM8168 环境搭建(1)
参考<DM81xx_DVR_RDK_Install_Guide.pdf> location:/dvrrdk/DVRRDK_04.01.00.02/dvr_rdk/docs 1,准备工作: ...
- 菜鸟Android之路(上)
自己为什么要学android 本人作为应届毕业生,自己进入社会前做过好多梦,可是呢,现实还是打败了无邪!!面对社会的压力和残酷的竞争力自己如何生成下去??我自己对自己说:第一步 先养活自己,才能走好以 ...
- 240多个jQuery插件
概述 jQuery 是继 prototype 之后又一个优秀的 Javascript 框架.其宗旨是—写更少的代码,做更多的事情.它是轻量级的 js 库(压缩后只有21k) ,这是其它的 js 库所不 ...
- sap中用函数增加断点(break point)
如果在增强程序中,每次调试都要去程序里面设置断点很麻烦,为了解决这个问题,可以用下面的两个方法: 1: if sy-uname eq 'XXXX' "XXX 为账号名字 break ...
- POJ 2992 Divisors
每个数都可以分解成素数的乘积: 写成指数形式:n=p1^e1*p2^e2*...*pn^en:(p都是素数) 那么n的因数的数量m=(e1+1)*(e2+1)*...*(en+1): 所以用筛选法筛出 ...
- VLAN间单臂路由访问
实验书上的拓朴图: 注意TRUNK端口和路由器子端口设置,可以承载不同的VLAN标签. 交换机(用2691加交换模块实现的): Building configuration... Current co ...
- 不同框架实现的WebService的服务端获取HttpServletRequest的方法
一. 基于xfire实现的WebService HttpServletRequest request = XFireServletController.getRequest(); 二. 基于axis实 ...
- 值得推荐的C/C++框架和库 very good
[本文系外部转贴,原文地址:http://coolshell.info/c/c++/2014/12/13/c-open-project.htm]留作存档 下次造轮子前先看看现有的轮子吧 值得学习的C语 ...
- Unreachable catch block for IOException. This exception is never thrown from the try statement body
Unreachable catch block for IOException. This exception is never thrown from the try statement body ...
- jQuery选择器上下文