Linux发送网络包的流程

1. 应用程序调用发送相关的系统调用

  • 应用程序调用 write()send()sendto() 等系统调用
  • 数据从用户空间复制到内核空间
  • 系统调用进入内核态,开始网络包发送流程

2. Socket 层处理

  • 根据 socket 类型(TCP/UDP)选择相应的传输层协议
  • 创建初始的 sk_buff (socket buffer) 结构体,这是内核中网络数据包的表示形式
  • 数据被放入 socket 的发送缓冲区

3. 传输层处理

对于 TCP 连接:

  • 将数据分段,确保每段不超过 MSS (最大分段大小)
  • 计算序列号、确认号等 TCP 头部信息
  • 实施拥塞控制、流量控制算法
  • 添加 TCP 头部到数据包

对于 UDP 连接:

  • 简单地添加 UDP 头部
  • 计算校验和

4. 网络层处理

  • 路由查找,确定数据包下一跳的目的地
  • 根据路由信息和 IP 协议添加 IP 头部
  • 如果数据包超过 MTU (最大传输单元),进行分片
  • 执行 netfilter 规则(iptables)

5. 网络设备层处理

  • 添加数据链路层头部(如以太网头部,包含 MAC 地址)
  • GSO (Generic Segmentation Offload) 可能会延迟分段,让网卡硬件来完成
  • 调用网络设备的发送接口

6. 流量控制/排队规则 (QDisc)

  • Linux 流量控制子系统 (tc) 对数据包进行排队和调度
  • 根据配置的 QDisc (排队规则) 决定发送顺序和时机
  • 常见排队规则:FIFO、SFQ (随机公平队列)、HTB (分层令牌桶) 等
  • 可以实现带宽限制、优先级控制等高级网络功能

7. 网卡驱动处理

  • 驱动程序将 sk_buff 转换为网卡理解的格式
  • 填充 Ring Buffer 的描述符,指向内存中的数据包
  • 通知网卡有新的数据包等待发送

8. DMA 传输到网卡

  • 网卡通过 DMA (直接内存访问) 从内存中读取数据包
  • 无需 CPU 参与,直接将数据从内存传输到网卡硬件
  • 网卡可能在此阶段执行 TSO (TCP 分段卸载) 等硬件优化

9. 网卡发送过程

  • 网卡完成最后的帧封装
  • 将数字信号转换为电信号/光信号等物理形式
  • 通过物理介质发送数据包到网络

10. 发送完成通知

  • 网卡完成发送后,触发硬件中断
  • 驱动程序处理中断,触发软中断通知传输层发送完成
  • 对于 TCP 连接,更新拥塞窗口等状态信息
  • 释放已发送的 sk_buff 结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值