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钩子点。

数据包接收路径内核旅程概览 数据包接收路径:网卡 → 应用层 ① 网卡硬件接收 DMA写入Ring Buffer ② 中断/NAPI调度 net_rx_action() ③ 链路层处理 __netif_receive_skb_core() ④ 网络层接收 ip_rcv() → NF_INET_PRE_ROUTING ⑤ 路由查找 ip_route_input() ⑥ 传输层接收 tcp_v4_rcv() ⑦ Socket队列 sock_queue_rcv_skb() ⑧ 应用层读取 recvfrom() / epoll Netfilter钩子点 • NF_INET_PRE_ROUTING • NF_INET_LOCAL_IN • NF_INET_FORWARD • NF_INET_POST_ROUTING • NF_INET_LOCAL_OUT 核心数据结构 • struct sk_buff (skb) • struct net_device • struct sock
常见面试陷阱: 不要混淆“数据包接收路径”和“数据包发送路径”。接收路径的核心入口是 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)和连接跟踪的基础。