【C语言】socket 层到网络接口的驱动程序之间的函数调用过程

一、socket 层到网络接口的驱动程序之间的函数调用过程概述

在 Linux 操作系统中,socket 层到网络接口的驱动程序之间的函数调用过程相对复杂,涉及多个层次的交互。以下是一个简化的概述,描述数据从 socket 传递到硬件驱动,再到硬件设备的基本调用过程:
1. 用户空间到内核空间
    用户程序通过 socket API 发起网络操作。当用户空间要发送数据时,它会调用如 sendto 或 write 等系统调用,这些调用将数据从用户空间传递到内核空间。
2. Socket 层处理
    根据 socket 类型(例如 TCP、UDP 或者其他协议),内核将调用相应的协议族处理函数。例如对于一个 TCP socket,传输控制协议 (TCP) 相关的函数将被使用。
3. 协议栈
    数据通过网络协议栈传递,进行必要的处理,如 IP 分段、TCP 分段、添加头部等。每一层协议栈都对数据进行加工,直到形成可以在网络上传输的包。
4. 路由决策
    内核根据 IP 层的路由表进行路由决策,确定用于发送数据的 net_device 结构体。此结构体代表了相应的网络接口,并包含了用于发送数据的接口函数。
5. 队列与传输
    数据包被放入到对应网络设备的发送队列中等待传输。这通常涉及到内核中的排队机制,如 Qdisc(排队规则)层。
6. 网络设备驱动程序的发送函数
    被排队的数据包最终将被网络设备驱动程序的发送函数处理。这一函数通常被称为 hard_start_xmit 或类似的名称。驱动程序将数据包转换成适合该网络设备的形式,并通过硬件接口发送出去。
7. 硬件传输
    最后,数据被传递到网卡的硬件,由网卡负责将电子信号或光信号发送到网络中。
这个过程可能会因为具体的配置和使用的协议栈而不同。在某些情况下,例如使用虚拟化技术或软件定义网络(SDN),过程中的某些步骤可能被跳过或者是在不同的层次上执行。此外,接收数据的过程也会涉及类似但相反的步骤,以将数据从硬件传输上来,经过内核处理,然后递送到用户态的应用程序中。

二、路由子系统将 IP 数据发送到正确的网络接口过程

在 Linux 内核中,IP层路由决策主要是由内核的路由子系统来完成的。路由子系统负责将 IP 数据包根据目的地址发送到正确的网络接口。这个过程大体上可以分为几个步骤:
1. 查找路由表
   当一个 IP 数据包需要被发送的时候,内核会根据这个数据包的目的 IP 地址在路由表中查找最匹配的路由项。Linux 中的路由表可以通过 ip route show 命令查看。
2. 路由表条目
   每一条路由表项包含了几个重要的信息字段,例如目的网络、子网掩码、网关、接口名称等。这些信息用来决定数据包的转发路径。
3. 选择最合适的路由
   如果路由表中有多条路由都可以匹配到一个目的地址,那么将根据优先级和其他标准选择最合适的一条。通常,最具体(最长前缀匹配)的路由将被选择用来转发数据包。
4. 确定 net_device
   一旦选择了一条路由,内核将使用与之相关联的 net_device 结构体。`net_device` 结构体代表了一个网络接口设备,包含了很多网络设备的信息,包括设备名称、接口状态、传输队列、以及用于发送和接收数据的函数指针等。
5. 处理网关(如果必要)
   如果数据包需要通过网关(跳)来到达目标,那么路由表项中也会包含网关的信息。在这种情况下,数据包的实际目的硬件地址将会是网关设备的地址,而不是最终目的地的地址。
6. 引用程序
   在最终确定了`net_device`结构体和下一跳信息(next hop—not necessarily the final destination)之后,数据包将被送到网络接口的发送队列准备发送(例如通过调用`dev_queue_xmit`函数)。
7. Neighbor Subsystem (ARP)
   如果还没有目的地的 MAC 地址,则需要进行地址解析(例如使用 ARP 协议解析 IPv4 地址)。这是在发送前必须完成的,除非目的地就是本地网络接口。
路由决策是一个动态的过程,可以被多种因素影响,例如路由协议、策略路由规则、网络接口的状态更改等。管理员或者网络管理系统可以修改路由表来更改路由决策的结果,以适应不断变化的网络环境。在进行网络通信时,确保高性能和正确的路由决策是很重要的,这是由内核的路由子系统来保证的。

三、选择路由的过程中涉及的步骤

当 Linux 内核需要发送一个网络数据包时,它会通过路由子系统来确定该往哪个方向发送数据包。选择路由之后,内核会使用与这条路由相关联的 net_device 结构体来处理接下来的数据包发送。`net_device` 结构体是 Linux 内核网络子系统的一个基础结构,代表一个网络接口,包含了与该网络设备相关的所有信息。
在选择路由的过程中,以下步骤通常会涉及:
1. 路由查找
   内核使用数据包的目的 IP 地址,通过路由查找函数(如 ip_route_output())在路由表中查找匹配的路由项。路由表包含了多个条目,每一个条目都包含目的网络、掩码、网关、接口等信息。
2. 选择路由项
   如果找到了匹配的路由项,内核就会获取相应的路由决策,这包括了数据包应该从哪个网络接口发送,以及是否需要通过网关来转发等信息。
3. 关联 net_device
   路由项包含了一个指向相关 net_device 结构体的指针。`net_device` 结构体定义在 <linux/netdevice.h> 头文件中,包含了网络接口的诸多信息和操作函数指针,如设备名(`name` 字段)、接口索引(`ifindex` 字段)、操作函数(`netdev_ops` 字段)等。
4. 数据包的处理
   一旦确定了 net_device,内核就会将数据包传递给这个结构体中的操作函数进行处理。`net_device_ops` 结构体中包含了多个操作数据包的函数指针,例如 ndo_start_xmit 用于发送数据包,`ndo_open` 和 ndo_stop 用于打开和关闭设备等。
5. 发送数据包
   ndo_start_xmit 函数(通常对应该网卡驱动的 hard_start_xmit 函数)被调用并且被传入待发送的 sk_buff(包含网络数据包的结构体)以及 net_device 结构体。该函数负责将数据包加入到传输队列,并触发数据包的传输流程,这可能会直接向硬件发送数据包,或者向硬件排队以便于稍后发送。
这个过程中的一个重要概念是 sk_buff,它是内核中用于存储和控制数据包的主要数据结构。当内核层的各种网络子系统处理数据包时,`sk_buff` 结构会随数据包传递,最终到达用于实际发送数据的网络设备驱动程序。

四、 IP 层数据包映射到相应的 net_device 结构体的过程

在 Linux 内核中,路由决策是基于路由表来进行的,其将 IP 层数据包映射到相应的 net_device 结构体的过程通常如下:
1. 网络接口注册
    当网络接口(或称为网络设备)如以太网卡在系统启动或者后来被加载时,它的驱动会通过调用 register_netdev() 函数将该设备注册到内核网络子系统中。在注册过程中,`net_device` 结构体会被初始化和填充,它包含了用于操作该网络设备的信息,包括发送和接收函数指针、设备名、以及设备的硬件地址等。
2. 路由表的初始化和更新
    路由表是内核中用于存储路由信息的数据结构,它包含了多个路由项,每个路由项包含了网络目的地址、网络掩码、网关地址、标志等信息。路由表可以手动通过例如 ip route add 命令配置,也可以自动通过 DHCP、路由协议如 OSPF、BGP 或其他机制来更新。
    当路由项被创建或更新时,每个路由项也会关联到一个 net_device 结构体。例如,如果一个路由项指定了通过特定的网关(也就是下一跳)来达到目的网络,则该路由项将包含指向该网关对应的网络接口(`net_device` 结构)的指针。
3. 路由选择
    当内核需要转发或发送数据包时,它会根据数据包的目的 IP 地址执行路由选择(路由查找)。这通常涉及查询路由表并且找到最合适的路由项。路由选择的算法会考虑多个因素,例如目的地址、子网掩码和度量值(metric)。
4. 结构体关联
    当路由选择过程确定了合适的路由项后,它会使用该路由项中指向 net_device 结构体的指针来确定数据包应该通过哪个网络接口发送。这个指针在路由项被添加到路由表时就已经建立起了。
路由表和网络设备通常是可以动态管理的,管理员可以使用包括 ifconfig、`ip` 等命令来配置网络接口和路由表,内核也会使用诸如 rtnetlink 接口来进行这些信息的更新和同步。

五、`net_device` 结构体中的设备名

`net_device` 结构体确实包含网络接口的名称,它在 Linux 内核网络子系统中表示一个网络接口。在 net_device 结构体中,通常有一个名为 name 的成员用于存储设备的名称。这个名称通常与在用户空间看到的设备名称(如 eth0, wlan0, ens33 等)相对应。
下面是一个简化版的 net_device 结构体的例子,展示了包含设备名称的部分:

struct net_device {char                name[IFNAMSIZ]; // 网络设备名称// ... 其他很多网络设备相关的成员变量和函数指针 ...// 这里仅展示了名称部分,并省略了大量其它细节
};

在这个结构体中,`IFNAMSIZ` 是一个定义在 <linux/if.h> 中的宏,它规定了接口名的最大长度,便于内核和用户空间的统一。
net_device 结构提供了内核中对网络接口的抽象,包含了很多网络操作的接口函数、统计信息、队列状态,以及一些特定于设备类型和配置的参数。
当网络接口注册到网络子系统时,例如在网卡驱动初始化的时候,这个结构会被填充并加入到内核的网络设备列表中。用户可以通过指令如 ifconfig 或 ip link show 在用户空间查看网络接口的详细信息。

六、IP 地址

在 Linux 内核中,`net_device` 结构体代表一个网络接口,它主要包含了与网络设备相关的信息,如设备状态、硬件地址(如 MAC 地址),以及指向设备驱动函数的指针等。`net_device` 结构体本身不直接保存 IP 地址信息。
IP 地址(无论是 IPv4 还是 IPv6)是在网络层管理的,具体而言,在 Linux 内核中,IP 地址是与网络接口相关联的,但存储在不同于 net_device 的结构体中。对于 IPv4,地址信息通常存储在 in_device 结构体中;对于 IPv6,地址信息通常存储在 inet6_dev 结构体中。
这两个结构体(`in_device` 和 inet6_dev)包含了与 IP 层相关的配置和状态信息,包括分配给接口的 IP 地址列表、子网掩码、任播和广播地址等。这些结构通过指针与对应的 net_device 实例相连。这样的设计允许网络接口能够同时配置和管理 IPv4 和 IPv6 地址。
网络接口的 IP 地址通常是通过系统调用(如 ioctl 或 socket 操作)和网络配置工具(如 ifconfig、`ip` 命令行工具等)来设置和管理的。在内核层面,此类操作会通过各种内核函数来修改和查看与 in_device 以及 inet6_dev 相关联的 IP 地址信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/695215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp播放mp4省流方案

背景&#xff1a; 因为项目要播放一个宣传和讲解视频&#xff0c;视频文件过大&#xff0c;同时还为了节省存储流量&#xff0c;想到了一个方案&#xff0c;用m3u8切片替代mp4。 m3u8&#xff1a;切片播放&#xff0c;可以理解为一个1G的视频文件&#xff0c;自行设置文…

【微服务生态】Dubbo

文章目录 一、概述二、Dubbo环境搭建-docker版三、Dubbo配置四、高可用4.1 zookeeper宕机与dubbo直连4.2 负载均衡 五、服务限流、服务降级、服务容错六、Dubbo 对比 OpenFeign 一、概述 Dubbo 是一款高性能、轻量级的开源Java RPC框架&#xff0c;它提供了三大核心能力&#…

总结Rabbitmq的六种模式

RabbitMQ六种工作模式 RabbitMQ是由erlang语言开发&#xff0c;基于AMQP&#xff08;Advanced Message Queue 高级消息队列协议&#xff09;协议实现的消息队列&#xff0c;它是一种应用程序之间的通信方法&#xff0c;消息队列在分布式系统开发中应用非常广泛。 RabbitMQ有六…

9.vue学习笔记(组件传递Props校验+组件事件-组件传递数据+组件事件-配合“v-model”使用)

文章目录 1.组件传递Props校验1.1.默认值1.2.必选项1.3.注意事项&#xff1a;props 是只读的 2.组件事件-组件传递数据2.1.温馨提示&#xff1a;组件之间传递数据的方案 3.组件事件-配合“v-model”使用 1.组件传递Props校验 Vue组件可以更细致地声明对传入的 props 的校验要求…

顺序表经典算法及其相关思考

27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 思路一 利用顺序表中的SLDestroy函数的思想&#xff0c;遇到等于val值的就挪动 思路二 双指针法&#xff1a;不停的将和val不相等的数字往前放。此时的des更像一个空数组&#xff0c;里面存放的都是和val不相等、能够存…

【人工智能学习思维脉络导图】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 知识图谱1. 基础知识2.人工智能核心概念3.实践与应用4.持续学习与进展5.挑战与自我提升6.人脉网络 知识图谱 人工智能学习思维脉络导图 1. 基础知识 计算机科学基础数学基础&#xff08;线性代数、微积分、概率论和统计学…

先进语言模型带来的变革与潜力

用户可以通过询问或交互方式与GPT-4这样的先进语言模型互动&#xff0c;开启通往知识宝库的大门&#xff0c;即时访问人类历史积累的知识、经验与智慧。像GPT-4这样的先进语言模型&#xff0c;能够将人类历史上积累的海量知识和经验整合并加以利用。通过深度学习和大规模数据训…

第十四章[面向对象]:14.5:访问限制/属性

一,动态添加属性/方法 1,动态添加实例属性和实例方法 from types import MethodTypeclass Student:passs = Student()# 动态添加属性 s.name = Tom print(s.name) print(s.__dict__)# 定义一个函数作为实例方法 def set_age(self, age):self.age = age# 动态添加方法 s.set_…

Nginx基础入门

一、Nginx的优势 nginx是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个SMTP&#xff08;邮局&#xff09;服务器。 Nginx的web优势&#xff1a;IO多路复用&#xff0c;时分多路复用&#xff0c;频分多路复用 高并发&#xff0c;IO多路复用&#xff0c;epoll&#xf…

【MySQL】学习连接查询和案例演示

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-KOxr1rwR9cQTlydJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

OD(8)之Mermaid流程图(flowcharts)使用详解

OD(8)之Mermaid流程图(flowcharts)使用详解 Author: Once Day Date: 2024年2月20日 漫漫长路才刚刚开始… 全系列文章可参考专栏: Linux实践记录_Once_day的博客-CSDN博客 参考文章: 关于 Mermaid | Mermaid 中文网 (nodejs.cn)Mermaid | Diagramming and charting tool‍…

聊一聊bpmn-js中的依赖注入框架didi

最近在用bpmn-js来进行flowable流程图的开发工作,不可避免地希望对其运行机制做一个大致的了解,在使用bpmn-js的过程中,bpmn-js基于diagram-js实现的插件式开发方式引起了我的兴趣。于是通过查阅源码希望对齐进一步了解发现:diagram-js是基于一个叫didi的实现的依赖注入功能…

C#通过泛型方法的重载分别调用主窗体和提示窗体

目录 一、涉及到的知识点 1.泛型方法的重载 2.使用泛型更好地实现通用化 二、示例&#xff1a;泛型方法及其重载 1.源码 2. 生成效果 实际开发项目时&#xff0c;有时会因为调用窗体或提示窗体过多&#xff0c;而难于管理&#xff0c;这时&#xff0c;可以通过泛型方法的…

【力扣hot100】刷题笔记Day8

前言 到了大章节【链表】了&#xff0c;争取两三天给它搞定&#xff01;&#xff01; 160. 相交链表 - 力扣&#xff08;LeetCode&#xff09;】 双指针 参考题解&#xff0c;相比于求长度右对齐再一起出发的方法简洁多了 class Solution:def getIntersectionNode(self, head…

基于FPGA的二维DCT变换和逆变换verilog实现,包含testbench

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 数据导入到matlab显示图像 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer:…

win32 汇编读文件

做了2个小程序&#xff0c;没有读成功&#xff1b;文件打开了&#xff1b; .386.model flat, stdcalloption casemap :noneinclude windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include Comdlg32.inc includelib …

2024-02-21 学习笔记(DETR)

自动多模态检测验证效果不佳&#xff08;过检太多&#xff09;后&#xff0c;节后开始尝试DETR路线。 基本梳理了下DETR发展和验证的脉络&#xff0c;先进行相应指定场景的效果验证。 关于DETR系列的介绍&#xff0c;B站上比较多&#xff0c;迪哥的都讲的比较细。 推荐大佬的…

如何在java中使用 Excel 动态函数生成依赖列表

前言 在Excel 中&#xff0c;依赖列表或级联下拉列表表示两个或多个列表&#xff0c;其中一个列表的项根据另一个列表而变化。依赖列表通常用于Excel的业务报告&#xff0c;例如学术记分卡中的【班级-学生】列表、区域销售报告中的【区域-国家/地区】列表、人口仪表板中的【年…

[计网底层小探索]:实现并部署多线程并发Tcp服务器框架(基于生产者消费者模型的线程池结构)

文章目录 一.网络层与传输层协议sockaddr结构体继承体系(Linux体系)贯穿计算机系统的网络通信架构图示: 二.实现并部署多线程并发Tcp服务器框架线程池模块序列化反序列化工具模块通信信道建立模块服务器主体模块任务回调模块(根据具体应用场景可重构)Tips:DebugC代码过程中遇到…

el-table同时固定左列和右列时,出现错误情况

最近遇到一个问题,就是需求是要求表格同时固定序号列和操作列,我们用的是饿了么组件库的el-table,如下图,出现了错误情况: 解决方法就是使用doLayout方法: 如果使用了keep-alive,可以在activated里执行doLayout方法: activated() {this.$nextTick(() => {this.$ref…