第八部分:Linux网络协议栈子系统
章节开篇
1. Linux网络协议栈的整体架构与分层设计
1.1 OSI七层模型与Linux协议栈的对应关系
OSI七层模型 | 核心职责 | Linux协议栈的对应实现 |
应用层 | 业务逻辑、应用协议(HTTP/HTTPS/MySQL等) | 用户态应用程序,内核不实现应用层协议 |
表示层 | 数据加密、解密、格式转换 | 合并到用户态应用层实现,内核仅提供加密算法接口 |
会话层 | 会话的建立、管理、断开 | 合并到用户态应用层,内核仅在Socket层提供连接管理基础能力 |
传输层 | 端到端的通信控制、端口寻址、可靠传输 | 内核态传输层:TCP、UDP、UDPLite、SCTP等协议实现 |
网络层 | 主机寻址、路由选择、数据包分片 | 内核态网络层:IPv4/IPv6、路由子系统、ICMP协议实现 |
数据链路层 | 帧封装、MAC寻址、差错校验 | 内核态链路层:网卡驱动上层、邻居子系统(ARP/NDISC)、网桥、TC流量控制 |
物理层 | 电信号/光信号的传输 | 物理网卡硬件、网卡驱动的底层硬件交互逻辑 |
1.2 Linux网络协议栈的实际分层架构
┌─────────────────────────────────────────────────────────────────┐ │ 用户态层:应用程序、glibc库、socket系统调用封装、curl/nginx等业务 │ └───────────────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 【Socket层】:统一的文件式IO接口,屏蔽底层协议差异,系统调用入口 │ │ 核心源码:net/socket.c、net/core/sock.c └───────────────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 【传输层】:端到端通信控制,端口寻址,可靠/不可靠传输保障 │ 核心协议:TCP、UDP、UDPLite、SCTP、DCCP │ 核心源码:net/ipv4/tcp_*.c、net/ipv4/udp.c、net/ipv6/ └───────────────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 【网络层】:主机寻址、路由选择、数据包分片与重组、跨网络转发 │ 核心协议:IPv4、IPv6、ICMP、IGMP │ 核心源码:net/ipv4/ip_*.c、net/ipv6/ip6_*.c、net/ipv4/route.c └───────────────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 【数据链路层】:帧封装、MAC寻址、邻居发现、流量控制、网桥转发 │ 核心模块:邻居子系统(ARP/NDISC)、TC流量控制、网桥、Bonding │ 核心源码:net/core/dev.c、net/ipv4/arp.c、net/bridge/、net/sched/ └───────────────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 【网卡驱动层】:硬件交互、数据包收发、中断处理、NAPI机制 │ 核心源码:drivers/net/ethernet/、net/core/dev.c、net/core/napi.c └───────────────────────────────┬─────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 物理层:网卡硬件、网线、交换机、路由器,电信号/光信号传输 │ └─────────────────────────────────────────────────────────────────┘各层核心职责详解
1.Socket层
2.传输层
- TCP:面向连接的可靠传输,通过三次握手建立连接、四次挥手断开连接,通过序列号、确认应答、超时重传、拥塞控制、流量控制保证数据的有序、无丢失、无重复;
- UDP:无连接的不可靠传输,仅提供端口寻址和校验和,不保证数据可达,优势是延迟低、开销小,适合实时音视频、DNS等场景。
3.网络层
4.数据链路层
5.网卡驱动层
1.3 数据包收发的总览流程
1.3.1 数据包接收的核心链路(网卡→用户态)
1. 物理网卡收到数据包,通过DMA把数据包写入内核预先分配的环形缓冲区(Ring Buffer) 2. 网卡触发硬件中断,通知CPU有新数据包到达 3. 中断顶半部:快速应答中断,关闭当前接收中断,触发软中断,唤醒NAPI调度 4. 软中断(NET_RX_SOFTIRQ):执行NAPI poll函数,从Ring Buffer批量读取数据包 5. 链路层:分配sk_buff结构体,封装数据包,解析以太网帧头,处理VLAN、网桥、TC规则 6. 网络层:解析IP头,路由判断(本地交付/转发),处理IP分片、防火墙规则(Netfilter) 7. 传输层:解析TCP/UDP头,根据源目IP+端口找到对应的Socket,把数据包放入Socket的接收缓冲区 8. Socket层:用户态进程通过recv()/read()系统调用,从Socket接收缓冲区读取数据到用户态缓冲区1.3.2 数据包发送的核心链路(用户态→网卡)
1. 用户态进程通过send()/write()系统调用,把数据从用户态缓冲区写入Socket的发送缓冲区 2. Socket层:校验Socket状态,调用传输层对应的发送接口 3. 传输层:封装TCP/UDP头,TCP协议处理序列号、拥塞控制、流量控制,把数据切分为MSS大小的段 4. 网络层:封装IP头,路由查找确定下一跳地址,处理IP分片、Netfilter防火墙规则 5. 链路层:通过ARP/NDISC获取下一跳的MAC地址,封装以太网帧头,处理TC流量控制、VLAN标签 6. 驱动层:把封装好的sk_buff放入网卡的发送环形缓冲区(TX Ring Buffer),通知网卡硬件发送 7. 网卡硬件通过DMA读取发送缓冲区的数据包,发送到网络,发送完成后触发中断,释放sk_buff资源1.4 协议栈的核心设计思想
1.分层解耦与标准化接口
2.软硬中断分离与NAPI机制
3.统一的数据包抽象:sk_buff
4.多核可扩展性设计
5.可扩展的钩子机制
6.内存池化管理
1.5 工程实践:协议栈基础信息查看
1.查看内核版本与协议栈基础信息
# 查看内核版本,确认协议栈的基础能力 uname -r # 查看内核编译时开启的网络协议特性 zcat /proc/config.gz | grep -E 'NET|TCP|UDP|IPV6' | head -202.查看网卡与驱动信息
# 查看所有网卡的基本信息 ip addr # 查看网卡的驱动、硬件特性、队列数量(核心) ethtool eth0 # 查看网卡的多队列配置(RSS队列数量) ethtool -l eth0 # 查看网卡的收发包统计、错误计数 ethtool -S eth03.查看Socket与连接状态
# 查看所有TCP/UDP连接,替代老旧的 netstat ss -tulnp # 查看TCP连接的详细状态(拥塞窗口、RTT、MSS等) ss -ti # 查看系统中所有Socket的统计信息 ss -s4.查看协议栈内核参数
# 查看所有网络相关的内核参数 sysctl -a | grep -E 'net.ipv4|net.ipv6|net.core' # 查看TCP相关的核心参数 sysctl -a | grep tcp_congestion_control sysctl -a | grep tcp_rmem sysctl -a | grep tcp_wmem5.查看网络协议栈的统计信息
# 查看TCP/UDP/IP协议的详细统计(收发包、错误、重传等) cat /proc/net/snmp # 查看TCP连接的详细状态统计 cat /proc/net/tcp # 查看软中断的统计信息,确认网络软中断的CPU分布 cat /proc/softirqs