Linux 网络收包流程

这篇具有很好参考价值的文章主要介绍了Linux 网络收包流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

哈喽大家好,我是咸鱼

我们在跟别人网上聊天的时候,有没有想过你发送的信息是怎么传到对方的电脑上的

又或者我们在上网冲浪的时候,有没有想过 HTML 页面是怎么显示在我们的电脑屏幕上的

无论是我们跟别人聊天还是上网冲浪,其实都依靠于计算机网络这项技术

计算机网络是指将多台计算机通过通信设备和传输介质连接在一起,使得它们之间能够相互通信、资源共享和协同工作

而计算机之间是通过数据包来实现信息传输和信息交换的,数据包是计算机网络中传输数据的基本单位

今天咸鱼将以 Linux 为例来给大家介绍一下 Linux 是如何实现网络接收数据包

网络协议栈&网络架构

在正文开始之前,我们先来了解一下 Linux 中的网络协议模型和网络子系统

  • 网络协议模型(网络协议栈)

在 Linux 中,Linux 网络协议栈分成了五层
Linux 网络收包流程
其中:

  • 应用层提供 socket 接口来供用户进程访问内核空间的网络协议栈

  • 传输层、网络层协议由 Linux 内核网络协议栈实现

  • 链路层协议靠网卡驱动来实现

  • 物理层协议由硬件网卡实现
    Linux 网络收包流程

  • 网络子系统(网络架构)

网络子系统是 Linux 内核中的一部分,由多个模块和驱动程序组成,它负责管理和控制系统的网络功能以实现网络通信

通过 Linux 网络子系统(网络架构)来实现上述网络协议模型

Linux 网络收包流程

其中

  • System call interface:为应用程序获取内核的网络系统提供了接口,例如 socket
  • Protocol agnostic interface:为和各种传输层协议的网络交互提供的一层公共接口
  • Network protocals:对各种传输层协议的实现,如 TCP、UDP、IP 等
  • Device agnostic interface:为各种底层网络设备抽象出的公共接口,与各种网络设备驱动连接在一起
  • Device drivers:与各种网络设备交互的驱动

收包过程

当 Linux 接收一个数据包的时候,这个包是怎么经过 Linux 的内核从而被应用程序拿到的呢?
Linux 网络收包流程

  • 到达网卡(NIC,Network Interface Card)

首先数据包到达网卡之后,网卡会校验接收到的数据包中的目的 MAC 地址是不是自己的 MAC 地址,如果不是的话通常就会丢弃掉

这种只接受发送给自己的数据包(其余的扔掉)的工作模式称为非混杂模式(Non-Promiscuous Mode)

混杂模式(Promiscuous Mode)则是网卡会接收通过网络传输的所有数据包,而不仅仅是发送给它自己的数据包

非混杂模式是网卡默认的工作模式,可以尽可能的保护网络安全和减少网络负载

网卡在校验完 MAC 地址之后还会校验数据帧(Data Frame)中校验字段 FCS 来一次确保接收到的数据包是正确的

  • 网卡硬件缓冲区 ——> 系统内存(ring buffer)

当网卡接收到数据包时,它将数据包的内容存储在硬件缓冲区中,然后通过 DMA 将接收到的数据从硬件缓冲区传输到系统内存中的指定位置,这个位置通常是一个环形缓冲区( ring buffer)

DMA(直接内存访问,Direct Memory Access)

DMA是一种数据传输技术,允许外设(如网卡、硬盘控制器、显卡等)直接访问计算机内存,而无需经过 CPU

通过 DMA 可以大大提高数据传输的效率,减轻 CPU 的负担

  • 触发硬中断

当网卡将数据包 DMA 到用于接收的环形缓冲区(rx_ring)之后,就会触发一个硬中断来告诉 CPU 数据包收到了

什么时候会触发一个硬中断,可以通过下面的参数来进行配置:

  • rx-usecs:当过这么长时间过后,一个中断就会被产生
  • rx-frames:当累计接收到这么多个数据帧后,一个中断就会被产生

上面的参数配置可以通过下面的命令来查看

# 以 CentOS 7 为例
ethtool -c <网卡名称>

当 ring buffer 满了之后,新来的数据包将给丢弃

ifconfig 查看网卡的时候,可以里面有个 overruns,表示因为环形队列满而被丢弃的包

CPU 收到硬中断之后就会停止手中的活,保存上下文,然后去调用网卡驱动注册的硬中断处理函数

为数据包分配 skb_buff ,并将接收到的数据拷贝到 skb_buff 缓冲区中

当一个数据包经过了网卡引起中断之后,每一个包都会在内存中分配一块区域,称为 sk_buff (套接字缓存,socket buffer )

sk_buff 是 Linux 网络的一个核心数据结构

  • 触发软中断

网卡的硬中断处理函数处理完之后驱动先 disable 硬中断,然后 enable 软中断

ps:待 ring buffer 中的所有数据包被处理完成后,enable 网卡的硬中断,这样下次网卡再收到数据的时候就会通知 CPU

内核负责软中断进程 ksoftirqd 发现有软中断请求到来,进行下面的一些操作

# 查看软中断进程
[root@localhost ~]# ps -ef | grep ksoftirqd

调用 net_rx_action 函数

它会通过 poll 函数去 rx_ring 中拿数据帧,获取的时候顺便把 rx_ring 上的数据给删除

static void net_rx_action(struct softirq_action *h)
{
    struct softnet_data *sd = &__get_cpu_var(softnet_data);
    unsigned long time_limit = jiffies + 2;
    int budget = netdev_budget;
    void *have;

    local_irq_disable();

    while (!list_empty(&sd->poll_list)) {
        ......
        n = list_first_entry(&sd->poll_list, struct napi_struct, poll_list);

        work = 0;
        if (test_bit(NAPI_STATE_SCHED, &n->state)) {
            work = n->poll(n, weight);
            trace_napi_poll(n);
        }

        budget -= work;
    }
}

除此之外,poll 函数会把 ring buffer 中的数据包转换成内核网络模块能够识别的 skb 格式(即 socket kernel buffer

socket kernel buffer (skb) 是 Linux 内核网络栈处理网络包(packets)所使用的 buffer,它的类型是 sk_buffer

3、最后进入 netif _receive_skb 处理流程,它是数据链路层接收数据帧的最后一关

根据注册在全局数组 ptype_allptype_base 里的网络层数据帧类型去调用第三层协议的接收函数处理

例如对于 ip 包来讲,就会进入到 ip_rcv;如果是 arp 包的话,会进入到 arp_rcv

  • 到达网络层(以 IP 协议为例)

IP 层的入口函数在 ip_rcv 函数,调用 ip_rcv 函数进入三层协议栈

首先会对数据包进行各种检查(检查 IP Header),然后调用 netfilter 中的钩子函数: NF_INET_PRE_ROUTING

netfilter: 是 Linux 内核中进行数据包过滤,连接跟踪(Connect Track),网络地址转换(NAT)等功能的主要实现框架

该框架在网络协议栈处理数据包的关键流程中定义了一系列钩子点(Hook 点),并在这些钩子点中注册一系列函数对数据包进行处理

这些注册在钩子点的函数即为设置在网络协议栈内的数据包通行策略,也就意味着,这些函数可以决定内核是接受还是丢弃某个数据包

NF_INET_PRE_ROUTING 会根据预设的规则对数据包进行判断并根据判断结果做相关的处理(修改或者丢弃数据包)

处理完成后,数据包交由 ip_rcv_finish 处理,该函数根据路由判决结果,决定数据包是交由本机上层应用处理,还是需要进行转发

如果是交由本机处理,则会交由 ip_local_deliver 本地上交流程;如果需要转发,则交由 ip_forward 函数走转发流程

  • 到达传输层(以 TCP 为例)

传输层 TCP 处理入口在 tcp_v4_rcv 函数,首先检查数据包的 TCP 头部等信息,确保数据包的完整性和正确性

然后去查找该数据包对应的已经打开的 socket ,如果找不到匹配的 socket,表示该数据包不属于任何一个已建立的连接,因此该数据包会被丢弃

如果找到了匹配的 socket,TCP 会进一步检查该 socket 和连接的状态,如果状态正常,TCP 会将数据包从内核传输到用户空间,放入 socket 的接收缓冲区(socket receive buffer)

  • 应用层获取数据

当数据包到达操作系统内核的传输层时,应用程序可以从套接字的接收缓冲区(socket receive buffer)中读取数据包

一般有两种方式读取数据,一种是 recvfrom 函数阻塞在那里等着数据来,这种情况下当 socket 收到通知后,recvfrom 就会被唤醒,然后读取接收队列的数据

另一种是通过 epoll 或者 select 监听相应的 socket,当收到通知后,再调用 recvfrom 函数去读取接收队列的数据

总结

网络模块可以说是 Linux 内核中最复杂的模块了

看起来一个简简单单的收包过程就涉及到许多内核组件之间的交互,如网卡驱动、协议栈,内核ksoftirqd 线程等

咸鱼原本打算把收包和发包的流程都写上的,但是光是写收包流程就就要了我半条命了,等下次有机会把发包的流程也写一下

总结一下 Linux 网络收包流程:文章来源地址https://www.toymoban.com/news/detail-600027.html

  • 数据到达网卡之后,网卡通过 DMA 将数据放到内存分配好的一块 ring buffer 中,然后触发硬中断
  • CPU 收到硬中断之后简单的处理了一下(分配 skb_buffer),然后触发软中断
  • 软中断进程 ksoftirqd 执行一系列操作(例如把数据帧从 ring ruffer上取下来)然后将数据送到三层协议栈中
  • 在三层协议栈中数据被进一步处理发送到四层协议栈
  • 在四层协议栈中,数据会从内核拷贝到用户空间,供应用程序读取
  • 最后被处在应用层的应用程序去读取

到了这里,关于Linux 网络收包流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux 网络发包流程

    哈喽大家好,我是咸鱼 之前咸鱼在《Linux 网络收包流程》一文中介绍了 Linux 是如何实现网络接收数据包的 简单回顾一下: 数据到达网卡之后,网卡通过 DMA 将数据放到内存分配好的一块 ring buffer 中,然后触发硬中断 CPU 收到硬中断之后简单的处理了一下(分配 skb_buffer ),

    2024年02月12日
    浏览(23)
  • 安卓协议逆向 咸鱼 frida rpc 调用方案

    通过frida rpc调用真机获取指定的搜索结果数据。 本文仅供大家学习及研究使用、切勿用于各种非法用途。 frida 提供了一种跨平台的 rpc (远程过程调用)机制,通过 frida rpc 可以在主机和目标设备之间进行通信,并在目标设备上执行代码,可实现功能如下: 1、动态地

    2024年02月07日
    浏览(29)
  • 咸鱼之王小游戏PC版鼠标模拟器实现

    最近朋友在玩咸鱼之王小游戏,用电脑挂机,由于火把缺乏,我看他经常疯狂的点鼠标攻击敌人。 我:\\\"你为什么不用鼠标模拟器去点?\\\" 朋友:\\\"鼠标模拟器点也不能干其他的事情,鼠标必须放到游戏窗口才行。\\\", 我:\\\"我帮你简单实现个鼠标模拟器吧\\\"  总结 其实原理很简单

    2024年02月12日
    浏览(92)
  • 【Linux网络】TCP/IP三次握手、四次挥手流程

    目录 一、三次握手,建立连接 二、四次挥手,断开连接 三、主要字段  1、标志位(Flags)  2、序号(sequence number)  3、确认号(acknowledgement number) 四、三次握手的报文变化 五、四次挥手的报文变化 六、面试题 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手,

    2024年02月08日
    浏览(39)
  • Linux network — 网络层收发包流程及 Netfilter 框架浅析

      本文主要对 Linux 系统内核协议栈中网络层接收,发送以及转发数据包的流程进行简要介绍,同时对 Netfilter 数据包过滤框架的基本原理以及使用方式进行简单阐述。   OSI 模型中将网络划分为七层,但在目前实际广泛使用的 TCP/IP 协议框架体系内,我们一般将网络划分为

    2024年01月18日
    浏览(27)
  • 大家现在都去做Linux运维了吗?

    运维自互联网出现以来,都是以基础技术部门的形式出现在各个互联网公司或者其他需要网络设备的公司里面,职位由来已久,也是多次徘徊在被淘汰的边缘。很多运维人都是靠着自己良好乐观的心态坚持到现在,接受新技术并学习新技术,及时调整规划自己的职业路线,希

    2023年04月13日
    浏览(31)
  • 使用近10年,说说向大家推荐Linux系统的理由

    使用linux已经快十年了,一直想推荐身边的使用linux,但是一直没有分享。但是现在我想分享推荐了。下面我们一起聊聊为什么我向大家推荐linux。 为什么现在我想推荐了呢?是因为我自认为相对于同龄人来说,我使用桌面版的时间算是挺长的了,而且我也想纠正一部分人不看

    2024年02月10日
    浏览(45)
  • 「网络编程」第二讲:socket套接字(四 - 完结)_ Linux任务管理与守护进程 | TCP协议通讯流程

    「前言」文章是关于网络编程的socket套接字方面的,上一篇是网络编程socket套接字(三),这篇续上篇文章的内容,下面开始讲解!  「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 「枫叶先生有点文青病」「句子分享」 Time goes on and on, never to an 

    2024年02月10日
    浏览(47)
  • linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手

    Tcp通信模拟实现与Udp通信模拟实现的区别不大,一个是面向字节流,一个是面向数据报;udp协议下拿到的数据可以直接发送,tcp协议下需要创建链接,用文件描述符完成数据的读写 1.1.1 接口认识 1.1.1.1 listen:监听socket 1.1.1.2 accept:获取连接 通信就用accept返回的文件描述符,

    2024年02月06日
    浏览(41)
  • 计算机视觉的应用12-卷积神经网络中图像特征提取的可视化研究,让大家理解特征提取的全过程

    大家好,我是微学AI,今天给大家介绍一下计算机视觉的应用12-卷积神经网络中图像特征提取的可视化研究,让大家理解特征提取的全过程。 要理解卷积神经网络中图像特征提取的全过程,我们可以将其比喻为人脑对视觉信息的处理过程。就像我们看到一个物体时,大脑会通

    2024年02月10日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包