我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Linux网络中数据包的接收过程是怎样的

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Linux网络中数据包的接收过程是怎样的

本篇文章为大家展示了Linux网络中数据包的接收过程是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

下面将介绍在Linux系统中,数据包是如何一步一步从网卡传到进程手中的。

如果英文没有问题,强烈建议阅读后面参考里的两篇文章,里面介绍的更详细。

小编只讨论以太网的物理网卡,不涉及虚拟设备,并且以一个UDP包的接收过程作为示例.

示例里列出的函数调用关系来自于kernel  3.13.0,如果你的内核不是这个版本,函数名称和相关路径可能不一样,但背后的原理应该是一样的(或者有细微差别)

网卡到内存

网卡需要有驱动才能工作,驱动是加载到内核中的模块,负责衔接网卡和内核的网络模块,驱动在加载的时候将自己注册进网络模块,当相应的网卡收到数据包时,网络模块会调用相应的驱动程序处理数据。

下图展示了数据包(packet)如何进入内存,并被内核的网络模块开始处理:

                   +-----+                    |     |                            Memroy +--------+   1     |     |  2  DMA     +--------+--------+--------+--------+ | Packet |-------->| NIC |------------>| Packet | Packet | Packet | ...... | +--------+         |     |             +--------+--------+--------+--------+                    |     |<--------+                    +-----+         |                       |            +---------------+                       |                            |                     3 | Raise IRQ                  | Disable IRQ                       |                          5 |                       |                            |                       &darr;                            |                    +-----+                   +------------+                    |     |  Run IRQ handler  |            |                    | CPU |------------------>| NIC Driver |                    |     |       4           |            |                    +-----+                   +------------+                                                    |                                                 6  | Raise soft IRQ                                                    |                                                    &darr;

数据包从外面的网络进入物理网卡。如果目的地址不是该网卡,且该网卡没有开启混杂模式,该包会被网卡丢弃。

网卡将数据包通过DMA的方式写入到指定的内存地址,该地址由网卡驱动分配并初始化。注: 老的网卡可能不支持DMA,不过新的网卡一般都支持。

网卡通过硬件中断(IRQ)通知CPU,告诉它有数据来了

CPU根据中断表,调用已经注册的中断函数,这个中断函数会调到驱动程序(NIC Driver)中相应的函数

 驱动先禁用网卡的中断,表示驱动程序已经知道内存中有数据了,告诉网卡下次再收到数据包直接写内存就可以了,不要再通知CPU了,这样可以提高效率,避免CPU不停的被中断。

 启动软中断。这步结束后,硬件中断处理函数就结束返回了。由于硬中断处理程序执行的过程中不能被中断,所以如果它执行时间过长,会导致CPU没法响应其它硬件的中断,于是内核引入软中断,这样可以将硬中断处理函数中耗时的部分移到软中断处理函数里面来慢慢处理。

内核的网络模块

软中断会触发内核网络模块中的软中断处理函数,后续流程如下

                                            +-----+                                     14      |     |                                +----------->| NIC |                                |            |     |                                |Enable IRQ  +-----+                                |                                |                          +------------+                                      Memroy                          |            |        Read           +--------+--------+--------+--------+         +--------------->| NIC Driver |<--------------------- | Packet | Packet | Packet | ...... |         |                |            |          9            +--------+--------+--------+--------+         |                +------------+         |                      |    |        skb    Poll | 8      Raise softIRQ | 6  +-----------------+         |                      |             10       |         |                      &darr;                      &darr; +---------------+  Call  +-----------+        +------------------+ | net_rx_action |<-------| ksoftirqd |        | napi_gro_receive | +---------------+   7    +-----------+        +------------------+                                                       |                                                       | 11                                                       &darr;                                            +--------------------------+    12      +------------------------+                                            | __netif_receive_skb_core |----------->| packet taps(AF_PACKET) |                                            +--------------------------+            +------------------------+                                                       |                                                       | 13                                                       &darr;                                              +-----------------+                                              | protocol layers |                                              +-----------------+

 内核中的ksoftirqd进程专门负责软中断的处理,当它收到软中断后,就会调用相应软中断所对应的处理函数,对于上面第6步中是网卡驱动模块抛出的软中断,ksoftirqd会调用网络模块的net_rx_action函数

net_rx_action调用网卡驱动里的poll函数来一个一个的处理数据包

在pool函数中,驱动会一个接一个的读取网卡写到内存中的数据包,内存中数据包的格式只有驱动知道

驱动程序将内存中的数据包转换成内核网络模块能识别的skb格式,然后调用napi_gro_receive函数

 napi_gro_receive会处理GRO相关的内容,也就是将可以合并的数据包进行合并,这样就只需要调用一次协议栈,接着调用__netif_receive_skb_core

 看是不是有AF_PACKET类型的socket(也就是我们常说的原始套接字),如果有的话,拷贝一份数据给它。tcpdump抓包就是抓的这里的包。

调用协议栈相应的函数,将数据包交给协议栈处理。

待内存中的所有数据包被处理完成后(即poll函数执行完成),启用网卡的硬中断,这样下次网卡再收到数据的时候就会通知CPU

协议栈

IP层

由于是UDP包,所以***步会进入IP层,然后一级一级的函数往下调:

|           |           &darr;         promiscuous mode &&       +--------+    PACKET_OTHERHOST (set by driver)   +-----------------+       | ip_rcv |-------------------------------------->| drop this packet|       +--------+                                       +-----------------+           |           |           &darr; +---------------------+ | NF_INET_PRE_ROUTING | +---------------------+           |           |           &darr;       +---------+       |         | enabled ip forword  +------------+        +----------------+       | routing |-------------------->| ip_forward |------->| NF_INET_FOWARD |       |         |                     +------------+        +----------------+       +---------+                                                   |           |                                                         |           | destination IP is local                                 &darr;           &darr;                                                 +---------------+  +------------------+                                       | dst_output_sk |  | ip_local_deliver |                                       +---------------+  +------------------+           |           |           &darr;  +------------------+  | NF_INET_LOCAL_IN |  +------------------+           |           |           &darr;     +-----------+     | UDP layer |     +-----------+
  • ip_rcv:  ip_rcv函数是IP模块的入口函数,在该函数里面,***件事就是将垃圾数据包(目的mac地址不是当前网卡,但由于网卡设置了混杂模式而被接收进来)直接丢掉,然后调用注册在NF_INET_PRE_ROUTING上的函数

  • NF_INET_PRE_ROUTING:  netfilter放在协议栈中的钩子,可以通过iptables来注入一些数据包处理函数,用来修改或者丢弃数据包,如果数据包没被丢弃,将继续往下走

  • routing: 进行路由,如果是目的IP不是本地IP,且没有开启ip forward功能,那么数据包将被丢弃,如果开启了ip  forward功能,那将进入ip_forward函数

  • ip_forward:  ip_forward会先调用netfilter注册的NF_INET_FORWARD相关函数,如果数据包没有被丢弃,那么将继续往后调用dst_output_sk函数

  • dst_output_sk: 该函数会调用IP层的相应函数将该数据包发送出去,同下一篇要介绍的数据包发送流程的后半部分一样。

  • ip_local_deliver:如果上面routing的时候发现目的IP是本地IP,那么将会调用该函数,在该函数中,会先调用NF_INET_LOCAL_IN相关的钩子程序,如果通过,数据包将会向下发送到UDP层

UDP层

 |          |          &darr;      +---------+            +-----------------------+      | udp_rcv |----------->| __udp4_lib_lookup_skb |      +---------+            +-----------------------+          |          |          &darr; +--------------------+      +-----------+ | sock_queue_rcv_skb |----->| sk_filter | +--------------------+      +-----------+          |          |          &darr; +------------------+ | __skb_queue_tail | +------------------+          |          |          &darr;  +---------------+  | sk_data_ready |  +---------------+
  • udp_rcv:  udp_rcv函数是UDP模块的入口函数,它里面会调用其它的函数,主要是做一些必要的检查,其中一个重要的调用是__udp4_lib_lookup_skb,该函数会根据目的IP和端口找对应的socket,如果没有找到相应的socket,那么该数据包将会被丢弃,否则继续

  • sock_queue_rcv_skb: 主要干了两件事,一是检查这个socket的receive  buffer是不是满了,如果满了的话,丢弃该数据包,然后就是调用sk_filter看这个包是否是满足条件的包,如果当前socket上设置了filter,且该包不满足条件的话,这个数据包也将被丢弃(在Linux里面,每个socket上都可以像tcpdump里面一样定义filter,不满足条件的数据包将会被丢弃)

  • __skb_queue_tail: 将数据包放入socket接收队列的末尾

  • sk_data_ready: 通知socket数据包已经准备好

调用完sk_data_ready之后,一个数据包处理完成,等待应用层程序来读取,上面所有函数的执行过程都在软中断的上下文中。

socket

应用层一般有两种方式接收数据,一种是recvfrom函数阻塞在那里等着数据来,这种情况下当socket收到通知后,recvfrom就会被唤醒,然后读取接收队列的数据;另一种是通过epoll或者select监听相应的socket,当收到通知后,再调用recvfrom函数去读取接收队列的数据。两种情况都能正常的接收到相应的数据包。

上述内容就是Linux网络中数据包的接收过程是怎样的,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Linux网络中数据包的接收过程是怎样的

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Linux网络中数据包的接收过程是怎样的

本篇文章为大家展示了Linux网络中数据包的接收过程是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。下面将介绍在Linux系统中,数据包是如何一步一步从网卡传到进程手中的。如果英文没有问题,强
2023-06-16

Linux网络包从中断到接收的示例分析

这期内容当中小编将会给大家带来有关Linux网络包从中断到接收的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。 linux既然要讲,那就把一个包的整个包生都说了算了触发中断在非虚拟化环境下,网卡通
2023-06-15

postfix邮件的接收和投递过程是怎样的

本篇文章给大家分享的是有关postfix邮件的接收和投递过程是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。postfix是Wietse Venema在IBM的GPL协议
2023-06-16

Python数据分析过程是怎样的

这篇文章主要介绍“Python数据分析过程是怎样的”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python数据分析过程是怎样的”文章能帮助大家解决问题。一、需求介绍该需求主要是分析某一种数据的历史
2023-06-26

linux系统数据恢复成功的过程是怎么样的

linux系统数据恢复成功的过程是怎么样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、磁盘阵列出现故障的过程本次进行数据恢复的是某个网站的一个2850型号服务器,这台
2023-06-05

SpringBoot中Mybatis+Druid数据访问过程是怎样的

本篇内容主要讲解“SpringBoot中Mybatis+Druid数据访问过程是怎样的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot中Mybatis+Druid数据访问过程是
2023-06-25

Linux系统中的Mysql安装过程是怎样的

这期内容当中小编将会给大家带来有关Linux系统中的Mysql安装过程是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Mysql是 Oracle 旗下得一款产品,属于关系型数据库,在 WEB 应用方
2023-06-28

Linux内核处理中断的过程是怎样的

Linux内核处理中断的过程是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。中断是现代 CPU 工作方式中重要的部分。例如:当你每次在键盘上按下一个按键后,CPU 会
2023-06-28

腾讯云服务器数据库怎样连接网络上网的

首先,在连接网络上网之前,我们需要确保自己的电脑已经安装了相应的软件和驱动程序,可以使用一些第三方软件进行驱动和网络适配器的检查和安装。同时,也需要确保自己的网络安全,例如防火墙、杀毒软件等,需要确保能够正常运行,避免网络安全漏洞被攻击者利用。其次,在连接网络上网的时候,我们需要注意一些细节。首先,需要确保自己的网络安
腾讯云服务器数据库怎样连接网络上网的
2023-10-28

腾讯云服务器数据库怎样连接网络的

腾讯云服务器数据库是用来存储和管理腾讯云服务器上的数据的,如果你想连接腾讯云服务器的网络,可以按照以下步骤进行连接:登录腾讯云服务器。在浏览器地址栏中输入https://tencentcloud.com/并按回车键进入腾讯云服务器主页。在腾讯云服务器主页右侧,有许多选项。选择其中一个选项,进入腾讯云服务器的配置选项。在配置选项页面中,你可以修改服务器的IP地址、数据库的连接模式或者其他的配
2023-10-26

在Linux系统中安装Docker的过程是怎样的

在Linux系统中安装Docker的过程是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在这篇博客中,我将引导您通过简单的步骤完成安装 Docker 的过程,安装dock
2023-06-22

python网络编程调用recv函数完整接收数据的三种方法

最近在使用python进行网络编程开发一个通用的tcpclient测试小工具。在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题。这里,简要介绍一下判别数据接收接收完成常用
2022-06-04

腾讯云服务器数据库怎样连接网络上网的设备

在选择合适的网络连接方式时,需要考虑以下因素:带宽:根据需要连接的设备数量和数据传输速率,选择适合的带宽。如果带宽太小,那么连接到云服务器的数据量将受限制;如果带宽太大,连接到云服务器的数据量也会受限制。距离:如果设备需要经过网络才能连接到云服务器,那么就需要考虑网络延迟和时延等因素。如果设备离云服务器太远,那么连接将
腾讯云服务器数据库怎样连接网络上网的设备
2023-10-28

腾讯云服务器数据库怎样连接网络使用的

一、选择合适的网络连接方式在使用腾讯云服务器数据库时,选择适合自己的网络连接方式是非常重要的。一般来说,企业和开发者在选择网络连接方式时可以考虑以下几个方面:选择适合自己的网络带宽:根据自己的业务需求和数据量选择合适的网络带宽,可以确保数据的传输速度和稳定性。选择适合自己的网络延迟:腾讯云服务器数据库的网络延迟是非常重
腾讯云服务器数据库怎样连接网络使用的
2023-10-28

linux主机中病毒处理过程是怎么样的

这期内容当中小编将会给大家带来有关linux主机中病毒处理过程是怎么样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。问题现象服务器一直往外大量发包,占用流量和cpu,导致服务器响应很慢甚至无响应,怀疑是
2023-06-05

编程热搜

目录