linux协议栈分析,linux内核协议栈

内存管理:一文读懂Linux内存组织结构及页面布局

1、内存是什么?

1)内存又称主存,是 CPU能直接寻址的存储空间,由半导体器件制成;

2)内存的特点是存取速率快,断电一般不保存数据,非持久化设备;

2、内存的作用

1)暂时存放 cpu的运算数据

2)硬盘等外部存储器交换的数据

3)保障 cpu计算机的稳定性和高性能

1、linux内存地址空间 Linux内存管理全貌

2、内存地址——用户态&内核态

3、内存地址——MMU地址转换

4、内存地址——分段机制

1)段选择符

更多Linux内核视频教程文档资料免费领取后台私信【内核】自行获取。

内核学习网站:

Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂

2)分段实现

5、内存地址——分页机制(32位)

6、用户态地址空间

7、内核态地址空间

8、进程内存空间

内存管理算法——对讨厌自己管理内存的人来说是天赐的礼物

1、内存碎片

1)基本原理

2)如何避免内存碎片

2、伙伴系统算法——组织结构

1)概念

2)外部碎片

3、伙伴系统算法——申请和回收

1)申请算法

2)回收算法

3)条件

4、如何分配 4M以上内存?

1)为何限制大块内存分配

2)内核中获取 4M以上大内存的方法

5、伙伴系统——反碎片机制

1)不可移动页

2)可回收页

6、slab算法——基本原理

1)基本概念

2)内部碎片

7、slab分配器的结构

详细参考:

经典|图解Linux内存性能优化核心思想

8、slab高速缓存

1)普通高速缓存

2)专用高速缓存

9、内核态内存池

1)基本原理

2)内核 API

10、用户态内存池

1) C++实例

11、DMA内存

1)什么是 DMA

2) DMA信号

out of memory的时代过去了吗?no,内存再充足也不可任性使用。

1、内存的使用场景

2、用户态内存分配函数

a)如果当前连续内存块足够 realloc的话,只是将 p所指向的空间扩大,并返回 p的指针地址。这个时候 q和 p指向的地址是一样的

b)如果当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p指向的内容 copy到 q,返回 q。并将 p所指向的内存空间删除

3、内核态内存分配函数

4、malloc申请内存

5、缺页异常

6、用户进程访问内存分析

7、共享内存

1)原理

2) shm接口

1、C内存泄露

2、C野指针

3、C资源访问冲突

4、STL迭代器失效

错误示例:删除当前迭代器,迭代器会失效

正确示例:迭代器 erase时,需保存下一个迭代器

5、C++ 11智能指针

(1)原理分析:

(2)数据结构:

(3)使用方法:

6、C++ 11更小更快更安全

六、如何查看内存

可以通过 cat/proc/slabinfo命令查看

可以通过/proc/sys/vm/drop_caches来释放

Linux内核协议栈丢弃SYN报文的主要场景剖析

在排查网络问题时,常遇到TCP连接建立失败。本文从TCP协议栈角度总结常见原因,集中于内核处理SYN报文阶段。若服务器端内核不回应SYNACK,通常与服务器端处理逻辑或特定配置相关,而非客户端重传SYN报文问题。

本文以CentOS 7内核版本为例,分析处于listen状态的socket处理TCP SYN报文的主要逻辑。关键代码逻辑在tcp_v4_conn_request()函数内。正常情况下,报文包含TCP SYN flag置位且请求队列未满。然而,实际情况中,该函数需考虑多种异常情况,其中一种涉及per-host PAWS检查。

per-host PAWS检查是一种防止sequence number缠绕的机制,尤其在NAT客户端访问服务器时常见。开启net.ipv4.tcp_tw_recycle和net.ipv4.tcp_timestamps时,此问题出现概率高。客户端在NAT环境下,新建连接时会出现时通时不通现象。此问题根源在于服务器快速回收TIME_WAIT状态时,NAT内部设备利用TCP option中timestamp字段的增长来判断串扰数据,导致新建连接被拒绝。

Linux内核实现中,接收SYN报文前需验证peer是否为proven,即进行per-host PAWS检查。在tcp_ipv4.c中,实现逻辑包含接收报文后检查timestamp是否增长。这一机制在NAT环境下的客户端带来副作用,即新建连接时通时不通。解决此问题的方法是关闭TIME-WAIT快速回收,调整net.ipv4.tcp_tw_recycle参数为0。

另一种主要场景涉及accept queue满情况,导致新来的SYN报文被丢弃。accept queue满通常发生在应用程序处理新连接时效率低下,导致无法及时从队列中获取连接。内核在判断accept queue满后,直接丢弃新来的SYN报文。

排查此类问题时,可利用ss命令查看实时情况及netstat-s统计进行历史分析。确认接受队列满或timestamp问题后,针对应用程序优化或调整内核参数进行解决方案。

总结,本文主要探讨了per-host PAWS检查和accept queue满导致的SYN报文丢弃两种常见场景,并详细描述了现象、原理、代码逻辑及排查方法。这些场景基本覆盖了TCP协议栈丢弃SYN报文的大部分问题。遇到其他场景时,需要结合特定配置和代码逻辑进行逐一排查。

linux 网络路径中网络协议栈有几种

1.总述

Linux中用户空间的网络编程,是以socket为接口,一般创建一个sockfd= socket(family,type,protocol),之后以该sockfd为参数,进行各种系统调用来实现网络通信功能。其中family指明使用哪种协议域(如INET、UNIX等),protocol指明该协议域中具体哪种协议(如INET中的TCP、UDP等),type表明该接口的类型(如STREAM、DGRAM等),一般设protocol=0,那么就会用该family中该type类型的默认协议(如INET中的STREAM默认就是TCP协议)。

Linux中利用module机制,层次分明地实现了这套协议体系,并具有很好的扩展性,其基本模块构成如下:

先看右边,顶层的socket模块提供一个sock_register()函数,供各个协议域模块使用,在全局的net_family[]数组中增加一项;各个协议域模块也提供一个类似的register_xx_proto()函数,供各个具体的协议使用,在该协议域私有的xx_proto[]数组中增加一项。这两个数组中的存放的都是指针,指向的数据结构如下图所示:

很明显它们是用来创建不同类型的socket接口的,且是一种分层次的创建过程,可想而知,顶层socket_create()完成一些共有的操作,如分配内存等,然后调用下一层create;协议域内的create()完成一些该协议域内共有的初始化工作;最后具体协议中的create()完成协议特有的初始化。具体的下一节讲。

再来看上图右边的,也是顶层socket模块提供的4个函数,前两个一般由具体协议模块调用,由于协议栈与应用层的交互,具体的后面会讲到。后两个一般有协议域模块调用,用于底层设备与协议栈间的交互。但这也不绝对,如在PPPOE协议中,这4个函数都由具体协议模块调用,这是因为PPPOX协议域内的共有部分不多,各个协议间几乎独立。这4个函数的功能及所用到的数据结构,在后面具体用到时会详细说明。

2.socket插口创建

首先来看一下最终创建好的socket插口由哪些部分组成,该结构是相当庞大的,这里只给出框架:

基本属性有state(listen、accept等),flags标志(blocked等),type类型,这里family和protocol都没有了,因为它们再创建时使用过了,已经被融入到socket结构中。

File指针指向一个file结构,在Linux中一个socket也被抽象为一个文件,所以在应用层一般通过标准的文件操作来操作它。

Ops指向一个struct proto_ops结构,它是每种协议特有的,应用层的系统调用,最终映射到网络栈中具体协议的操作方法。

Sk指向一个struct sock结构,而该结构在分配空间时,多分配了一点以作为该协议的私有部分,这里包含了该协议的具体信息,内容相当多。首先是一个struct sock_common结构,包含了协议的基本信息;然后是一个sk_prot_create指针,指向一个struct proto结构体,该结构体就是第一节中所述的,用proto_regsiter()注册到内核中的,它包含应用层到协议栈的交互操作和信息(也可以说成是Appà transport layer的交互信息);然后还有一个sk_backlog_rcv函数指针,所指函数在协议栈处理完接收到的包之后调用,一般仅是把数据包放到该socket的接收队列中,等待APP读取;最后协议的私有部分里存放该协议的私有信息,如pppoe的sessionID、daddr,tcp的连接4元组等,这些信息很重要,利用它们来区分同一个协议中的多个socket。

附上出处链接:

阅读剩余
THE END