1. 网络协议栈总览:Linux网络协议栈架构、OSI与TCP/IP模型对应关系、数据包在内核中的旅程概览
本章是《Linux内核网络协议栈面试高频问题与工程实战》的开篇。我们将从宏观视角俯瞰Linux网络协议栈的整体架构,理清OSI七层模型与TCP/IP四层模型的对应关系,并追踪一个数据包从网卡到应用层的完整内核旅程。理解这些基础脉络,是后续深入分析协议栈各模块(如Netfilter、路由子系统、Socket层)的前提。
1.1 Linux网络协议栈分层架构
Linux内核网络协议栈采用分层设计,每一层职责清晰,层与层之间通过标准接口交互。这种设计借鉴了TCP/IP模型,并针对内核实现做了优化。从下到上,主要分为以下层次:
| 层次 | 内核模块/子系统 | 核心职责 | 关键数据结构/函数 |
|---|---|---|---|
| 物理/数据链路层 | 网络设备驱动、NAPI | 收发包、中断处理、DMA传输 | struct net_device, sk_buff |
| 网络层 | IPv4/IPv6、路由子系统、Netfilter | 路由查找、分片重组、防火墙过滤 | struct iphdr, struct dst_entry, nf_hook_ops |
| 传输层 | TCP/UDP协议模块 | 连接管理、流量控制、可靠传输 | struct tcphdr, struct udphdr, struct sock |
| 套接字层 | BSD Socket、INET Socket | 提供统一系统调用接口(read/write/sendmsg) |
struct socket, struct sock, struct proto_ops |
| 应用层 | 用户态进程(Nginx、Redis等) | 业务逻辑处理 | 系统调用接口 |
面试高频点: 面试官常问“数据包从网卡到应用层经历了哪些内核函数?” 核心路径是:
net_rx_action → __netif_receive_skb_core → ip_rcv → nf_hook_slow (PREROUTING) → ip_route_input → tcp_v4_rcv → tcp_v4_do_rcv → sock_queue_rcv_skb。
1.2 OSI与TCP/IP模型对应关系
OSI七层模型是理论标准,TCP/IP模型是事实标准。Linux内核协议栈的实现更贴近TCP/IP模型,但理解两者的映射关系有助于面试时回答“分层解耦”相关问题。
| OSI七层模型 | TCP/IP四层模型 | Linux内核对应实现 | 典型协议/设备 |
|---|---|---|---|
| 应用层 | 应用层 | 用户态进程、系统调用 | HTTP, DNS, SSH |
| 表示层 | (通常由应用库实现) | SSL/TLS (OpenSSL) | |
| 会话层 | (通常由应用库实现) | SOCKS, RPC | |
| 传输层 | 传输层 | TCP/UDP协议模块 | TCP, UDP, SCTP |
| 网络层 | 网络层 | IPv4/IPv6、路由、Netfilter | IP, ICMP, ARP |
| 数据链路层 | 网络接口层 | 网络设备驱动、MAC层 | Ethernet, VLAN, Bridge |
| 物理层 | 网卡硬件、PHY芯片 | RJ45, 光纤, 无线 |
工程实战要点: 在排查网络问题时,要明确问题发生在哪一层。例如,
ping 不通可能是网络层(路由)问题,也可能是数据链路层(ARP)问题。使用 tcpdump 抓包时,理解各层头部结构(Ethernet header → IP header → TCP/UDP header)是分析报文的基础。
1.3 数据包在内核中的旅程概览(接收路径)
下面这张SVG图描绘了一个TCP数据包从网卡到达用户态应用的核心路径,重点标注了关键内核函数和Netfilter钩子点。
常见面试陷阱: 不要混淆“数据包接收路径”和“数据包发送路径”。接收路径的核心入口是
net_rx_action(NAPI轮询),而发送路径的核心入口是 dev_queue_xmit。另外,Netfilter钩子在接收路径上挂载在 NF_INET_PRE_ROUTING 和 NF_INET_LOCAL_IN,在发送路径上挂载在 NF_INET_LOCAL_OUT 和 NF_INET_POST_ROUTING。
1.4 数据包在内核中的旅程概览(发送路径)
发送路径是接收路径的逆过程,但细节不同。应用层通过系统调用 sendmsg 将数据送入内核,经过Socket层、传输层(TCP分段/UDP封装)、网络层(路由、分片)、链路层(帧封装),最终通过网卡发送出去。
| 步骤 | 内核函数/模块 | 关键操作 |
|---|---|---|
| 1. 系统调用 | __sys_sendmsg |
从用户态拷贝数据到内核skb |
| 2. Socket层 | tcp_sendmsg / udp_sendmsg |
构建传输层头部,管理发送缓冲区 |
| 3. 传输层 | tcp_write_xmit / udp_send_skb |
TCP拥塞控制、滑动窗口;UDP直接封装 |
| 4. 网络层 | ip_queue_xmit / ip_output |
路由查找、IP分片、Netfilter钩子(LOCAL_OUT) |
| 5. 链路层 | dev_queue_xmit |
排队规则(Qdisc)、帧封装、唤醒网卡发送 |
| 6. 网卡驱动 | ndo_start_xmit |
DMA传输、发送完成中断 |
工程实战要点: 发送路径的瓶颈常出现在
dev_queue_xmit 的Qdisc排队阶段。如果遇到TCP发送延迟或丢包,可以使用 tc 命令查看队列规则(如pfifo_fast、fq_codel),或者调整 net.core.default_qdisc 内核参数。对于高性能场景,建议使用 busy_poll 或 XDP 来绕过部分内核路径。
1.5 本章小结
- 分层架构: Linux网络协议栈分为设备层、网络层、传输层、套接字层和应用层,层间通过标准接口(如
sk_buff)传递数据。 - 模型对应: OSI七层模型与TCP/IP四层模型并非严格一一对应,Linux内核实现更贴近TCP/IP模型,但理解OSI有助于面试时阐述分层思想。
- 数据包旅程: 接收路径的核心函数链是
net_rx_action→ip_rcv→tcp_v4_rcv→sock_queue_rcv_skb;发送路径的核心函数链是tcp_sendmsg→ip_queue_xmit→dev_queue_xmit。 - Netfilter钩子: 在接收和发送路径的关键位置插入了Netfilter钩子,这是实现防火墙(iptables/nftables)、网络地址转换(NAT)和连接跟踪的基础。