监控和调整Linux网络协议栈的图解指南:接收数据
Table of Contents
入门
最初设定
数据到达
网络数据处理开始
网络数据处理继续
协议栈和用户态套接字
结论
监视和调整Linux网络协议栈:接收数据(图解):https://rtoax.blog.csdn.net/article/details/108629964
这篇博客文章是在我们之前的博客文章《监视和调整Linux网络堆栈:接收数据》的基础上扩展的,该图表带有一系列旨在帮助读者更清晰地了解Linux网络堆栈工作原理的图表。
监视或调整Linux网络堆栈没有捷径可走。如果有希望对其进行调整或优化,操作员必须努力充分理解各种系统及其相互作用。也就是说,上一篇博客文章的篇幅可能使读者难以概念化各种系统之间的交互方式。希望这篇博客文章能帮助您解决这一问题。
入门
这些图旨在概述Linux网络堆栈的工作方式。因此,许多细节被排除在外。为了获得完整的图片,鼓励读者阅读我们的博客文章,其中详细介绍了网络堆栈的各个方面:监视和调整Linux网络堆栈:接收数据。这些图的目的是帮助读者形成一个心理模型,以了解内核中的某些系统如何在高层进行交互。
让我们先来看一些重要的初始设置,这对于理解数据包处理是必需的。
最初设定
设备具有多种方式来提醒计算机系统的其余部分某些工作已准备就绪,可以进行处理。在网络设备的情况下,NIC通常会提高IRQ来发出信号,表示已到达数据包并准备好进行处理。当Linux内核执行IRQ处理程序时,它以非常高的优先级运行,并经常阻止生成其他IRQ。因此,设备驱动程序中的IRQ处理程序必须尽快执行,并将所有长时间运行的工作推迟到此上下文之外执行。这就是为什么存在“ softIRQ”系统的原因。
Linux内核中的“ softIRQ”系统是内核用来处理设备驱动程序IRQ上下文之外的工作的系统。对于网络设备,softIRQ系统负责处理传入的数据包。softIRQ系统在内核引导过程中及早初始化。
上图对应于我们网络博客文章的softIRQ部分,并显示了softIRQ系统及其每CPU内核线程的初始化。
softIRQ系统的初始化如下:
- 软中断内核线程被创建(每个CPU的一个)中
spawn_ksoftirqd
的内核/ softirq.c中与一个呼叫smpboot_register_percpu_thread
从内核/ smpboot.c。从代码中可以看出,该函数run_ksoftirqd
列为thread_fn
,这是将在循环中执行的函数。 - ksoftirqd线程开始在
run_ksoftirqd
函数中执行其处理循环。 - 接下来,
softnet_data
创建结构,每个CPU一个。这些结构包含对用于处理网络数据的重要数据结构的引用。我们将再次看到的是poll_list
。的poll_list
就是NAPI调查工人结构将通过向呼叫添加napi_schedule
或设备驱动程序等NAPI的API。 net_dev_init
然后NET_RX_SOFTIRQ
通过调用将softirq 注册到softirq系统open_softirq
,如此处所示。注册的处理程序函数称为net_rx_action
。这是softirq内核线程将执行以处理数据包的功能。
图上的步骤5-8与要处理的数据的到达有关,将在下一节中提到。继续阅读以了解更多!
数据到达
数据从网络到达!
当网络数据到达NIC时,NIC将使用DMA将数据包数据写入RAM。对于igb
网络驱动程序,在RAM中设置一个环形缓冲区,指向接收到的数据包。重要的是要注意,某些NIC是“多队列” NIC,这意味着它们可以将传入的数据包DMA到RAM中的许多环形缓冲区之一。正如我们将很快看到的那样,此类NIC能够利用多个处理器来处理传入的网络数据。了解有关多队列NIC的更多信息。为了简化起见,上图仅显示了一个环形缓冲区,但是根据您使用的NIC和硬件设置,您的系统上可能会有多个队列。
在网络博客文章的此部分中阅读下面描述的有关过程的更多详细信息。
让我们逐步了解接收数据的过程:
- NIC从网络接收数据。
- NIC使用DMA将网络数据写入RAM。
- NIC发出IRQ。
- 执行设备驱动程序的注册IRQ处理程序。
- IRQ在NIC上被清除,因此它可以为新的数据包到达生成IRQ。
- NAPI softIRQ轮询循环从对的调用开始
napi_schedule
。
调用将napi_schedule
触发上图中的步骤5-8的开始。正如我们将看到的,NAPI softIRQ轮询循环是通过简单地翻转位域中的一个位并将一个结构添加到poll_list
for 来开始的。没有其他工作可以完成,napi_schedule
而这正是驱动程序将处理推迟到softIRQ系统的方式。
继续使用上一节中的数字继续上一节中的图:
napi_schedule
在驱动程序中对的调用将驱动程序的NAPI轮询结构添加到poll_list
当前CPU的。- 设置softirq挂起位,以便
ksoftirqd
此CPU上的进程知道有要处理的数据包。 run_ksoftirqd
函数(由ksoftirq
内核线程循环运行)执行。__do_softirq
调用,检查未决的位字段,查看softIRQ是否未决,并调用为未决的softIRQ注册的处理程序:net_rx_action
这将对传入的网络数据进行所有繁重的处理。
请务必注意,softIRQ内核线程正在执行net_rx_action
,而不是设备驱动程序IRQ处理程序。
网络数据处理开始
现在,数据处理开始。该net_rx_action
函数(从ksoftirqd
内核线程调用)将开始处理已添加到poll_list
当前CPU的所有NAPI轮询结构。在两种一般情况下添加了轮询结构:
- 从设备驱动程序调用
napi_schedule
。 - 在接收数据包控制的情况下使用处理器间中断。阅读有关“接收数据包导向”如何使用IPI处理数据包的更多信息。
我们将首先介绍从中获取驱动程序的NAPI结构时发生的情况poll_list
。(下一节将介绍如何为RPS向IPI注册的NAPI结构)。
上面的图在此处进行了深入说明),但可以总结如下:
net_rx_action
循环通过检查NAPI轮询列表中的NAPI结构开始。- 的
budget
和经过时间进行检查,以确保软中断不会独占CPU时间。 - 注册的
poll
函数称为。在这种情况下,该功能igb_poll
由igb
驱动程序注册。 - 驱动程序的
poll
功能从RAM中的环形缓冲区中获取数据包。 - 数据包被移交给
napi_gro_receive
,这将处理可能的通用接收卸载。 - 数据包要么为GRO保留,调用链就在此处结束,要么将数据包传递到
net_receive_skb
协议栈。
接下来,我们将看到如何net_receive_skb
处理接收数据包控制以在多个CPU之间分配数据包处理负载。
网络数据处理继续
网络数据处理从继续netif_receive_skb
,但是数据的路径取决于是否启用了接收数据包导向(RPS)。默认情况下,“即用型” Linux内核不会启用RPS,并且如果要使用它,则需要显式启用和配置RPS。
在禁用RPS的情况下,请使用上图中的数字:
netif_receive_skb
将数据传递到__netif_receive_core
。
__netif_receive_core
将数据传递到任何水龙头(例如PCAP)。__netif_receive_core
将数据传递给已注册的协议层处理程序。在许多情况下,这就是ip_rcv
IPv4协议栈已注册的功能。
在启用RPS的情况下:
netif_receive_skb
将数据传递到enqueue_to_backlog
。- 数据包被放置在每个CPU输入队列中进行处理。
- 远程CPU的NAPI结构已添加到该CPU中
poll_list
,并且IPI已排队,如果尚未运行,它将触发远程CPU上的softIRQ内核线程唤醒。 - 当
ksoftirqd
远程CPU上的内核线程运行时,它遵循上一部分中描述的相同模式,但是这次,已注册的poll
函数是process_backlog
从当前CPU的输入队列中收集数据包。 - 数据包传递到
__net_receive_skb_core
。 __netif_receive_core
将数据传递到任何水龙头(例如PCAP)。__netif_receive_core
将数据传递给已注册的协议层处理程序。在许多情况下,这就是ip_rcv
IPv4协议栈已注册的功能。
协议栈和用户态套接字
接下来是协议栈,netfilter,berkley数据包过滤器,最后是userland套接字。该代码路径很长,但是线性且相对简单。
您可以继续遵循网络数据的详细路径。路径的简要概述是:
- 数据包由IPv4协议层使用接收
ip_rcv
。 - 执行Netfilter和路由优化。
- 发送给当前系统的数据将传递到更高级别的协议层,例如UDP。
- 分组由UDP协议层与所接收的
udp_rcv
和被排队到接收由缓冲一用户态插座udp_queue_rcv_skb
和sock_queue_rcv
。在排队到接收缓冲区之前,对伯克利包过滤器进行处理。
请注意,在此过程中,多次查询了netfilter。确切的位置可以在我们的详细演练中找到。
结论
Linux网络堆栈非常复杂,并且有许多不同的系统相互作用。调优或监视这些复杂系统的任何努力都必须努力理解它们之间的相互关系以及一个系统中的设置更改将如何影响其他系统。
这篇(很少)插图化的博客文章试图使我们更长的博客文章更易于管理和理解。
监控和调整Linux网络协议栈的图解指南:接收数据相关推荐
- 监视和调整Linux网络协议栈:发送数据
目录 有关监视和调整Linux网络堆栈的一般建议 总览 详细外观 协议族注册 通过套接字发送网络数据 sock_sendmsg,__sock_sendmsg和__sock_sendmsg_nosec ...
- 监视和调整Linux网络协议栈:接收数据
Table of Contents 有关监视和调整Linux网络协议栈的建议 总览 详细外观 网络设备驱动程序 初始化 网络设备初始化 启动网络设备 监控网络设备 调整网络设备 SoftIRQ 什么是 ...
- Linux网络协议栈:中断下半部处理
<Linux中断处理:上半部和下半部> <Linux网络协议栈:中断下半部处理> 目录 数据包上送 网络中断下半部处理 总结 推荐阅读 在<Linux网络协议栈:网络包接 ...
- Linux网络协议栈:关闭一个还有没发送数据完的TCP连接
<监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...
- Linux网络协议栈:网络包接收过程
目录 一 Linux网络收包总览 二 Linux启动 2.1 创建ksoftirqd内核线程 2.2 网络子系统初始化 2.3 协议栈注册 2.4 网卡驱动初始化 2.5 启动网卡 三 迎接数据的到来 ...
- Linux网络协议栈:NAPI机制与处理流程分析(图解)
Table of Contents NAPI机制 NAPI缺陷 使用 NAPI 先决条件 非NAPI帧的接收 netif_rx - 将网卡中收到的数据包放到系统中的接收队列中 enqueue_to_b ...
- Linux网络协议栈:一个TCP链接的耗时
<一次系统调用开销到底有多大?strace.time.perf命令> 目录 一 正常TCP连接建立过程 二 TCP连接建立时的异常情况 1)客户端connect系统调用耗时失控 2)半/全 ...
- Linux网络协议栈:网卡收包分析
Table of Contents 网卡收包 一,框架 二,初始化 三,驱动收包 四,内核处理 参考文章 推荐阅读 网卡收包 内核网络模块如何初始化? 内核如何通过网卡驱动收发数据包? 驱动收到的数据 ...
- linux 虚拟机大量udp请求失败_理解 Linux 网络栈:Linux 网络协议栈简单总结分析...
1. Linux 网络路径 1.1 发送端 1.1.1 应用层 (1) Socket 应用层的各种网络应用程序基本上都是通过 Linux Socket 编程接口来和内核空间的网络协议栈通信的.Linu ...
最新文章
- python爬虫正则表达式实例-python爬虫 正则表达式解析
- HTML 5常用的交互元素————内容交互元素(2)
- Leetcode 300 最长递增子序列 (每日一题 20210803)
- 深度剖析hdfs原理
- scrapy学习资料汇总
- linux物理内存地址与iomem,一种Linux系统物理内存镜像文件分析方法_4
- unity怎么导入系统的树_unity3d 随机添加树木
- windows10下anaconda安装、tensorflow安装以及pythonchar配置的使用
- JS缺失错误- Uncaught SyntaxError: Unexpected token
- 以太网安全技术ACL原理+配置
- mysql的数据库的索引_MySql数据库索引原理
- 微服务框架自带uuid生成器
- 【读书笔记《Bootstrap 实战》】4.企业网站
- Think中文网站产品驱动程序一览表ThinkPad T61 for Win XP
- 关于如何连接网络打印机
- linux xdm 启动执行文件,Linux下配置XDM登录服务器
- Python|判断字符串是否符合日期要求
- variable argument parameter的区别
- 计算机专业到底该不该考研?
- python3豆瓣电影排行榜爬取