Linux是如何接收数据包的

本文详细解释了Linux系统如何在启动时为接收网络数据包做准备,包括创建ksoftirqd内核线程、初始化网络子系统、注册协议栈、初始化网卡驱动以及启动网卡的过程。着重介绍了硬中断和软中断的处理,以及网络协议栈如何处理接收到的数据包。
摘要由CSDN通过智能技术生成

Linux是如何接收数据包的

1. 流程总览

在这里插入图片描述

  1. 当网卡收到数据后,以DMA的方式把收到的帧写入内存,再向CPU发起一个中断,通知CPU有数据到达
  2. 当CPU收到中断请求后,会去调用网络设备注册的中断处理函数(此过程称为硬中断),然后发出软中断请求,很快就会释放CPU资源
  3. ksoftirqd内核线程检测到有软中断到达,调用poll开始轮询收包
  4. 帧会从RingBuffer这个环上摘下来,保存为一个struct_sk_buff(一种特殊的数据结构)
  5. 各层协议开始处理网络帧,处理完之后的数据会被放到socket的接收队列中
  6. 应用程序从socket接收队列获取到数据包,完成收包过程

2. Linux启动时为接收网络包做了哪些准备?

2.1 创建ksoftirqd内核线程

ksoftirqd检测软中断到达,才能调用poll函数收包,因此在系统收包时,一定会先创建好这个线程

在这里插入图片描述
系统初始化的时候会执行到spawn_ksoftirqd,来创建出softirqd线程

当softirqd被创建出来后,他就会进入自己的线程循环函数ksoftirqd_should_run和run_ksoftirqd了。接下来判断有没有软中断需要处理

这个线程的数量等于CPU的核数

2.2 初始化网络子系统

网络子系统初始化过程中,会为每个CPU初始化softnet_data,也会为RX_SOFTIRQ和TX_SOFTIRQ注册处理函数(可以简单理解RX就是接收,TX就是发送)

在这里插入图片描述

可以看出,系统发数据包和接收数据包的软中断会执行不同的函数

2.3 注册协议栈

内核实现了网络层的IP协议,也实现了传输层的TCP协议和UDP协议。这些协议对应的实现函数分别是ip_rcv()、tcp_v4_rcv()和udp_rcv()。

内核是通过注册的方式来实现的。Linux内核中的fs_initcall和subsys_initcall类似,也是初始化模块的入口。fs_initcall调用net_init后开始注册网络协议栈,通过inet_init,将这些函数注册到inet_protos和ptype_base数据结构中
在这里插入图片描述
inet_protos记录着UDP、TCP的处理函数地址,ptype_base存储着ip_rcv()函数的处理地址。软中断会通过ptype_base找到ip_rcv函数地址,进而将IP包正确地送到ip_rcv()中执行。在ip_rcv()中将会通过inet_protos找到TCP或者UDP的处理函数,再把包转发给udp_rcv()或者tcp_v4_rcv()函数

而ip_rcv这个处理函数的具体过程,就是iptable netfilter等等,udp_rcv函数会判断socket接收队列是否满了等等

2.4 初始化网卡驱动

每一个驱动程序会使用module_init向内核注册一个初始化函数,当驱动程序被加载时,内核会调用这个函数,然后内核就知道了该驱动的相关信息,比如igb网卡驱动的igb_driver_name和igb_probe函数地址。
在这里插入图片描述

当网卡设备被识别后,内核会调用其驱动的probe方法,让设备处于ready状态。

网卡驱动实现了ethtool所需要的接口,也在这里完成函数地址的注册。当ethtool发起一个系统调用之后,内核会找到对于操作的回调函数。ethtool之所以能查看网卡收发统计、修改网卡自适应模式、调整RX队列的数量和大小,是因为最终调用到了网卡驱动的相应方法

2.5 启动网卡

在这里插入图片描述
igb_open调用了igb_setup_all_tx_resources和igb_setup_all_rx_resources,在igb_setup_all_rx_resources这一步,分配了RingBuffer,并建立内存和Rx队列的映射关系

一个RingBuffer的内部不是仅有一个环形队列数组,而是有两个
在这里插入图片描述

3. 收包过程

3.1 硬中断处理

当数据帧从网线到达网卡时,第一站是网卡的接收队列。网卡在分配给自己的RingBuffer中寻找可用的内存位置(RingBuffer满的时候,新来的数据包会被丢弃,如果ifconfig发现overruns有丢包,可以通过ethtool加大环形队列的长度),找到后DMA引擎会把数据DMA到网卡之前关联的内存里,这个时候CPU是没有感知的。DMA完成以后,网卡会向CPU发起一个硬中断,通知CPU有数据到达
在这里插入图片描述

硬中断处理过程非常短,记录一个寄存器,修改CPU的poll_list然后发出一个软中断就结束了

3.2 软中断处理

在这里插入图片描述

3.3 网络协议栈处理

netif_receive_skb函数会根据包的协议进行处理,假如是UDP包,将包依次送到ip_rcv、udp_rcv等函数处理

在这里插入图片描述

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值