Linux的协议栈是什么东西?它其实是Linux内核中实现网络通信功能的一组子系统与代码模块的总称,遵循TCP/IP分层思想,负责把网线上的电信号变成应用程序能读到的字节流,也负责把应用数据封装成包发出去。

协议栈的主要层次
从内核源码角度看,Linux协议栈可粗略分为以下几层:
- 网卡驱动与链路层:接收帧、校验、交给上层
- 网络层(IP层):处理路由、分片、ICMP等
- 传输层:TCP、UDP的收发与连接管理
- 套接字层(socket):向用户态提供统一接口
数据包接收流程
当网卡收到数据,会发起硬中断,内核把帧挂到每CPU的接收队列,随后由软中断(NET_RX_SOFTIRQ)调用协议栈处理函数。下面是一段简化逻辑的代码示意:
// 伪代码:软中断中处理接收
static void net_rx_action(struct softirq_action *h)
{
struct sk_buff *skb;
while ((skb = poll_queue()) != NULL) {
// 进入协议栈,根据以太类型分发
if (skb->protocol == htons(ETH_P_IP)) {
ip_rcv(skb); // IP层处理
}
}
}
// IP层进一步交给传输层
int ip_rcv(struct sk_buff *skb)
{
// 校验头长度、 checksum
return ip_local_deliver(skb);
}
发送方向怎么走
应用程序调用write或sendto时,数据从socket层往下,经TCP/UDP封装、IP路由查找、邻居子系统填MAC,最终由驱动放到网卡发送队列。可用sendto()函数举例:
// 用户态发送UDP包 int fd = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(8080); inet_pton(AF_INET, "192.168.0.1", &addr.sin_addr); sendto(fd, "hello", 5, 0, (struct sockaddr*)&addr, sizeof(addr)); // 内核依次走 sock_sendmsg -> udp_sendmsg -> ip_output
为什么理解它有用
知道Linux的协议栈是什么东西,就能明白为何tcpdump能在设备层抓包,为何丢包可能发生在sk_buff队列满时,也更容易读懂内核参数如net.core.rmem_max的含义。它是排查网络问题和做性能调优的基础。
Linux协议栈不是孤立模块,而是和内存管理、进程调度紧密协作的内核基础设施。
小结
Linux协议栈是内核里分层处理网络数据的机制,涵盖驱动到socket。把握收发包路径,是深入Linux网络的第一步。