当前位置: 首页 > news >正文

深入Linux内核理解socket的本质

本文将从一个初学者的角度开始聊起,让大家了解 Socket 是什么以及它的原理和内核实现。

一、Socket 的概念

Socket 就如同我们日常生活中的插头与插座的连接关系。在网络编程中,Socket 是一种实现网络通信的接口或机制。 想象一下,插头插入插座后,电流得以流通,实现了能量的传递。而在网络世界里,当一个程序使用 Socket 与另一台机子建立“连接”时,就如同插头成功插入了插座,数据能够在两者之间进行流通和交换。

例如,当我们在网上聊天时,发送方的程序通过 Socket 将消息发送出去,接收方的程序通过对应的 Socket 接收这些消息。又比如在下载文件时,下载程序通过 Socket 与提供文件的服务器建立连接,从而能够获取到所需的文件数据。总之,它是网络通信的端点,用于在不同的计算机进程之间进行通信,而计算机中通过五元组:协议类型、源IP地址、源端口号、目标IP地址、目标端口号,通过五元组来唯一

二、Socket 的使用场景

我们想要将数据从 A 电脑的某个进程发到 B 电脑的某个进程。如果需要确保数据能发给对方,就选可靠的 TCP 协议;如果数据丢了也没关系,就选择不可靠的 UDP 协议。初学者一般首选 TCP。

这时就需要用 socket 进行编程,首先创建关于 TCP 的 socket:

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>int main() {int sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock_fd == -1) {std::cerr << "Failed to create socket" << std::endl;return 1;}// 后续代码...return 0;
}

这个方法会返回 sock_fd,它是 socket 文件的句柄。

对于服务端,得到 sock_fd 后,依次执行 bind()、listen()、accept() 方法,等待客户端的连接请求;对于客户端,得到 sock_fd 后,执行 connect() 方法向服务端发起建立连接的请求,此时会发生 TCP 三次握手。

连接建立完成后,客户端可以执行 send() 方法发送消息,服务端可以执行 recv() 方法接收消息,反之亦然。

三、Socket 的设计

现在我们抛开socket,重新设计一个内核网络传输功能。我们想要将数据从 A 电脑的某个进程发到 B 电脑的某个进程,从操作上来看,就是发数据给远端和从远端接收数据,也就是写数据和读数据。

但这里有两个问题:

  1. 接收端和发送端可能不止一个,因此需要用 IP 和端口做区分,IP 用来定位是哪台电脑,端口用来定位是这台电脑上的哪个进程。

  2. 发送端和接收端的传输方式有很多区别,如可靠的 TCP 协议、不可靠的 UDP 协议,甚至还需要支持基于 icmp 协议的 ping 命令。

为了支持这些功能,需要定义一个数据结构 sock,在 sock 里加入 IP 和端口字段。这些协议虽然各不相同,但有一些功能相似的地方,可以将不同的协议当成不同的对象类(或结构体),将公共的部分提取出来,通过“继承”的方式复用功能。

于是,定义了一些数据结构:

sock 是最基础的结构,维护一些任何协议都有可能会用到的收发数据缓冲区。

在 Linux 内核 2.6 相关的源码中,sock 结构体的定义可能类似于:

struct sock {// 相关字段struct sk_buff_head sk_receive_queue; // 接收数据缓冲区struct sk_buff_head sk_write_queue;  // 发送数据缓冲区// 其他可能的字段
};

inet_sock 特指用了网络传输功能的 sock,在 sock 的基础上还加入了 TTL、端口、IP 地址这些跟网络传输相关的字段信息。比如 Unix domain socket,用于本机进程之间的通信,直接读写文件,不需要经过网络协议栈。

可能的定义:

struct inet_sock {struct sock sk; // 继承自 sock__be32 port;    // 端口__be32 saddr;   // IP 地址// 其他相关字段
};

inet_connection_sock 是指面向连接的 sock,在 inet_sock 的基础上加入面向连接的协议里相关字段,比如 accept 队列、数据包分片大小、握手失败重试次数等。虽然现在提到面向连接的协议就是指 TCP,但设计上 Linux 需要支持扩展其他面向连接的新协议。

例如:

struct inet_connection_sock {struct inet_sock inet; // 继承自 inet_sockstruct request_sock_queue accept_queue; // accept 队列// 其他相关字段
};

tcp_sock 就是正儿八经的 TCP 协议专用的 sock 结构,在 inet_connection_sock 基础上还加入了 TCP 特有的滑动窗口、拥塞避免等功能。同样 UDP 协议也会有一个专用的数据结构,叫 udp_sock。

大概如下:

struct tcp_sock {struct inet_connection_sock icsk; // 继承自 inet_connection_sock// TCP 特有的字段,如滑动窗口、拥塞避免等相关字段
};

有了这套数据结构,将它跟硬件网卡对接一下,就实现了网络传输的功能。

四、提供 Socket 层

由于这里面的代码复杂,还操作了网卡硬件,需要较高的操作系统权限,再考虑到性能和安全,于是将它放在操作系统内核里。

为了让用户空间的应用程序使用这部分功能,将这部分功能抽象成简单的接口,将内核的 sock 封装成文件。创建 sock 的同时也创建一个文件,文件有个文件描述符 fd,通过它可以唯一确定是哪个 sock。将fd暴露给用户,用户就可以像操作文件句柄那样去操作这个 sock 。

struct file{//文件相关的字段.....void *private_data; //指向sock
}

创建socket时,其实就是创建了一个文件结构体,并将private_data字段指向sock。

有了 sock_fd 句柄后,提供了一些接口,如 send()、recv()、bind()、listen()、connect() 等,这些就是 socket 提供出来的接口。

所以说,socket 其实就是个代码库或接口层,它介于内核和应用程序之间,提供了一堆接口,让我们去使用内核功能,本质上就是一堆高度封装过的接口。

我们平时写的应用程序里代码里虽然用了socket实现了收发数据包的功能,但其 实真正执行网络通信功能的,不是应用程序,而是linux内核。

在操作系统内核空间里,实现网络传输功能的结构是sock,基于不同的协议和应用场景,会被泛化为各种类型的xx_sock,它们结合硬件,共同实现了网络传输功能。为了将这部分功能暴露给用户空间的应用程序使用,于是引入了socket层,同时将sock嵌入到文件系统的框架里,sock就变成了一个特殊的文件,用户就可以在用户空间使用文件句柄,也就是socket_fd来操作内核sock的网络传输能力。

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

五、Socket 如何实现网络通信

以最常用的 TCP 协议为例,实现网络传输功能分为建立连接和数据传输两个阶段。

(一)建立连接

在客户端,执行 socket 提供的 connect(sockfd, "ip:port") 方法时,会通过 sockfd 句柄找到对应的文件,再根据文件里的信息指向内核的 sock 结构,通过这个 sock 结构主动发起三次握手。

在服务端,握手次数还没达到“三次”的连接叫半连接,完成好三次握手的连接叫全连接,它们分别会用半连接队列和全连接队列来存放,这两个队列会在执行 listen() 方法的时候创建好。当服务端执行 accept() 方法时,就会从全连接队列里拿出一条全连接。

虽然都叫队列,但半连接队列其实是个哈希表,而全连接队列其实是个链表。

在 Linux 内核 2.6 版本的源码中,相关的代码实现可能位于网络子系统的部分。例如,建立连接的过程可能涉及到 tcp_connect() 等函数。

(二)数据传输

为了实现发送和接收数据的功能,sock 结构体里带了一个发送缓冲区和一个接收缓冲区,其实就是个链表,上面挂着一个个准备要发送或接收的数据。

当应用执行 send() 方法发送数据时,会通过 sock_fd 句柄找到对应的文件,根据文件指向的 sock 结构,找到这个 sock 结构里带的发送缓冲区,将数据放到发送缓冲区,然后结束流程,内核看心情决定什么时候将这份数据发送出去。

接收数据流程也类似,当数据送到 Linux 内核后,先放在接收缓冲区中,等待应用程序执行 recv() 方法来拿。

当应用进程执行 recv() 方法尝试获取(阻塞场景下)接收缓冲区的数据时,如果有数据,取走就好;如果没数据,就会将自己的进程信息注册到这个 sock 用的等待队列里,然后进程休眠。如果这时候有数据从远端发过来了,数据进入到接收缓冲区时,内核就会取出 sock 的等待队列里的进程,唤醒进程来取数据。

当多个进程通过 fork 的方式 listen 了同一个 socket_fd,在内核它们都是同一个 sock,多个进程执行 listen() 之后,都会将自身的进程信息注册到这个 socket_fd 对应的内核 sock 的等待队列中。在 Linux 2.6 以前,会唤醒等待队列里的所有进程,但最后其实只有一个进程会处理这个连接请求,其他进程又重新进入休眠,会消耗一定的资源,这就是惊群效应。在 Linux 2.6 之后,只会唤醒等待队列里的其中一个进程,这个问题被修复了。

服务端 listen 的时候,那么多数据到一个 socket 怎么区分多个客户端的?以 TCP 为例,服务端执行 listen 方法后,会等待客户端发送数据来。客户端发来的数据包上会有源 IP 地址和端口,以及目的 IP 地址和端口,这四个元素构成一个四元组,可以用于唯一标记一个客户端。服务端会创建一个新的内核 sock,并用四元组生成一个 hash key,将它放入到一个 hash 表中。下次再有消息进来的时候,通过消息自带的四元组生成 hash key 再到这个 hash 表 里重新取出对应的 sock 就好了。

六、Socket 怎么实现“继承”

Linux 内核是 C 语言实现的,而 C 语言没有类也没有继承的特性,是通过结构体里的内存是连续的这一特点来实现“继承”的效果。将要继承的“父类”,放到结构体的第一位,然后通过结构体名的长度来强行截取内存,这样就能转换结构体,从而实现类似“继承”的效果。

例如:

struct tcp_sock {/* inet_connection_sock has to be the first member of tcp_sock */struct inet_connection_sock inet_conn;// 其他字段
};struct inet_connection_sock {/* inet_sock has to be the first member! */struct inet_sock icsk_inet;// 其他字段
};// sock 转为 tcp_sock
static inline struct tcp_sock *tcp_sk(const struct sock *sk) {return (struct tcp_sock *)sk;
}

七、总结

  • socket 中文套接字,可理解为一套用于连接的数字。

  • sock 在内核,socket_fd 在用户空间,socket 层介于内核和用户空间之间。

  • 在操作系统内核空间里,实现网络传输功能的结构是 sock,基于不同的协议和应用场景,会被泛化为各种类型的 xx_sock,它们结合硬件,共同实现了网络传输功能。为了将这部分功能暴露给用户空间的应用程序使用,于是引入了 socket 层,同时将 sock 嵌入到文件系统的框架里,sock 就变成了一个特殊的文件,用户就可以在用户空间使用文件句柄,也就是 socket_fd 来操作内核 sock 的网络传输能力。

  • 服务端可以通过四元组来区分多个客户端。

  • 内核通过 C 语言“结构体里的内存是连续的”这一特点实现了类似继承的效果。

相关文章:

深入Linux内核理解socket的本质

本文将从一个初学者的角度开始聊起&#xff0c;让大家了解 Socket 是什么以及它的原理和内核实现。 一、Socket 的概念 Socket 就如同我们日常生活中的插头与插座的连接关系。在网络编程中&#xff0c;Socket 是一种实现网络通信的接口或机制。 想象一下&#xff0c;插头插入…...

Python使用爬虫IP抓取数据过程

用户之前询问了不同语言的爬虫示例&#xff0c;特别是Python、Node.js和Ruby。现在他们希望详细扩展Python版本中使用代理IP的过程。 用户可能已经掌握了基本的爬虫编写&#xff0c;但遇到了IP被封的问题&#xff0c;或者想防止被封。他们需要知道如何集成代理IP到现有的代码中…...

通过MCP+数据库实现AI检索和分析

通过 MCP&#xff08;Multi-Agent Collaboration Platform&#xff0c;多智能体协作平台&#xff09; 数据库&#xff0c;实现一个AI检索和分析系统。 一、系统目标 实现通过 AI 多智能体对结构化&#xff08;数据库&#xff09;和非结构化&#xff08;文档、文本&#xff09…...

51单片机烧录程序演示教程

51单片机烧录程序演示教程 51单片机是一种经典的8位单片机&#xff0c;广泛应用于嵌入式系统开发中。烧录程序是指将编译好的代码下载到单片机的存储器中&#xff0c;以便单片机能够按照程序运行。以下是详细的烧录流程和步骤。 所需工具和材料 硬件&#xff1a; 51单片机开发…...

06软件测试需求分析案例-添加用户

给职业顾问部的老师添加用户密码后&#xff0c;他们才能登录使用该软件。只有admin账户具有添加用户、修改用户信息、删除用户的权利。admin是经理或团队的第一个人的账号&#xff0c;后面招一个教师就添加一个账号。 通读需求是提取信息&#xff0c;提出问题&#xff0c;输出…...

Asp.NET Core WebApi IOptions<T>详解

IOptions<T> 是 ASP.NET Core 中用于访问配置数据的一个接口&#xff0c;它属于 Microsoft.Extensions.Options 命名空间。通过 IOptions<T>&#xff0c;你可以将配置绑定到强类型的类中&#xff0c;并在应用程序的不同部分中注入和使用这些配置。这种方式不仅使得…...

Gartner发布软件供应链安全市场指南:软件供应链安全工具的8个强制功能、9个通用功能及全球29家供应商

攻击者的目标是由开源和商业软件依赖项、第三方 API 和 DevOps 工具链组成的软件供应链。软件工程领导者可以使用软件供应链安全工具来保护他们的软件免受这些攻击的连锁影响。 主要发现 越来越多的软件工程团队现在负责解决软件供应链安全 (SSCS) 需求。 软件工件、开发人员身…...

(四十三)Dart 中的空安全与 `required` 关键字

Dart 中的空安全与 required 关键字 空安全&#xff08;Null Safety&#xff09; 空安全&#xff08;Null Safety&#xff09;是 Dart 语言的一项重要特性&#xff0c;旨在帮助开发者避免空指针异常&#xff08;NullPointerException&#xff09;。空安全通过在编译时检查变量…...

《解锁分布式软总线:构建智能设备统一管理平台》

智能设备的数量呈爆发式增长&#xff0c;从智能家居里的各类电器&#xff0c;到智能办公中的电脑、打印机&#xff0c;再到工业领域的各种自动化设备&#xff0c;不一而足。如何对这些纷繁复杂的智能设备进行有效管理&#xff0c;成为摆在我们面前的一道难题。分布式软总线技术…...

【android bluetooth 协议分析 01】【HCI 层介绍 1】【hci_packets.pdl 介绍】

在 AOSP 的蓝牙协议栈 (Gabeldorsche) 中&#xff0c;hci_packets.pdl 是一个 协议描述语言文件&#xff0c;用于定义 HCI (Host Controller Interface) 层的数据包结构和通信协议。以下是详细解析&#xff1a; 1. 文件作用 system/gd/hci/hci_packets.pdl 协议自动化生成&…...

远程升级组件设计

----------------------- | 主应用程序 | ---------------------- | 通信接口&#xff08;使用本地socket通信发送给远程升级模块进程或者线程 | (如何启动进程程execl或execv函数&#xff09;,启动线程用std::sthread。 v ---------------------- 远程升级模块 ----------…...

Kubernetes集群环境搭建与初始化

1.Kubernetes简介&#xff1a; Kubernetes是Google开源的一个容器编排引擎&#xff0c;它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时&#xff0c;通常要部署该应用的多个实例以便对应用请求进行负载均衡。 在Kubernetes中&#xff0c;我…...

Compose 适配 - 响应式排版 自适应布局

一、概念 基于可用空间而非设备类型来设计自适应布局&#xff0c;实现设备无关性和动态适配性&#xff0c;避免硬编码&#xff0c;以不同形态布局更好的展示内容。 二、区分可用空间 WindowSizeClasses 传统根据屏幕大小和方向做适配的方式已不再适用&#xff0c;APP的显示方式…...

5G_WiFi_CE_DFS

目录 一、规范要求 1、法规目录 2、定义 3、运行模式 4、主/从设备相关的运行行为及具体的动态频率选择&#xff08;DFS&#xff09;要求 5、产品角色确定测试项目 6、测试项目 测试项1&#xff1a;信道可用性检查&#xff08;Channel Availability Check&#xff09; …...

Lalamove基于Flink实时湖仓演进之路

摘要&#xff1a;本文投稿自货拉拉国际化技术部 资深数据仓库工程师林海亮老师。内容分为以下几个部分&#xff1a; 1、业务简介 2、Flink 在业务中的应用与挑战 3、实时数仓架构的 Flink 驱动演进 4、未来展望 一、业务简介 Lalamove 于2013年在香港成立&#xff0c;是货拉拉的…...

【含文档+PPT+源码】基于微信小程序的卫生院预约挂号管理系统的设计与实现

项目视频介绍&#xff1a; 毕业作品基于微信小程序的卫生院预约挂号管理系统的设计与实现 课程简介&#xff1a; 本课程演示的是一款基于微信小程序的卫生院预约挂号管理系统的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习…...

人工智能100问☞第2问:机器学习的核心原理是什么?

目录 一、通俗解释 二、专业解析 三、权威参考 机器学习的核心原理是​​通过数据训练模型,使计算机自动发现数据中的内在规律或模式,并利用这些规律对新数据做出预测或决策​​。这一过程强调数据驱动(从经验中学习)、模型优化(通过损失函数和参数调整提升性能)以及泛…...

【深度学习基础】——机器的神经元:感知机

感知机模型的原理之前已经讲过&#xff08;【感知机模型 - CSDN App】https://blog.csdn.net/2401_88885149/article/details/145563837?sharetypeblog&shareId145563837&sharereferAPP&sharesource2401_88885149&sharefromlink&#xff09;但主要是从数学和机…...

OpenCV 图形API(29)图像滤波-----GMat类

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::GMat 是 OpenCV 的 G-API 模块中的一个核心类&#xff0c;用于定义计算图中的数据节点。G-API 是 OpenCV 中的一个模块&#xff0c;旨在通过…...

spark的堆外内存,是在jvm内还是操作系统内存内?

在 Apache Spark 中&#xff0c;堆外内存&#xff08;Off-Heap Memory&#xff09;是直接分配在操作系统的物理内存中&#xff0c;而非 JVM 堆内内存。以下是详细的解释&#xff1a; 1. 堆外内存的本质 操作系统管理 Spark 的堆外内存直接通过操作系统分配&#xff08;例如使用…...

AD9253 LVDS 高速ADC驱动开发

1、查阅AD9253器件手册 2、查阅Xilinx xapp524手册 3、该款ADC工作在125Msps下&#xff0c;14bit - 2Lane - 1frame 模式。 对应&#xff1a;data clock时钟为500M DDR mode。data line rate&#xff1a;1Gbps。frame clock&#xff1a;1/4 data clock 具体内容&#xff1a;…...

swift菜鸟教程14(闭包)

一个朴实无华的目录 今日学习内容&#xff1a;1.Swift 闭包1.1闭包定义1.2闭包实例1.3闭包表达式1.3.1sorted 方法&#xff1a;据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。1.3.2参数名称缩写&#xff1a;直接通过$0,$1,$2来顺序调用闭包的参数。1.3.3运算符函…...

【HarmonyOS NEXT+AI】问答02:有一点编程基础,可以学不?

在“HarmonyOS NEXTAI大模型打造智能助手APP(仓颉版)”课程里面&#xff0c;有学员问&#xff0c;有一点编程基础&#xff0c;可以学不&#xff1f; 这里统一做下回复。 学习本课程只需要掌握任一编程语言即可&#xff0c;拥有JavaScript、TypeScript、ArkTS或Java语言基础更佳…...

maven 依赖的优先级

最短路径优先 工程中依赖了a、b两个jar包&#xff0c; 在a jar包内引用了b jar包版本为1.0&#xff0c;路径为&#xff1a;Project > a > b(1.0) 工程中直接依赖的b jar包版本为2.0&#xff0c;路径为&#xff1a;Project > b(2.0) 由于b(2.0)路径最短&#xff0…...

Java实现音频录音播放机功能

Java实现一个简单的音频录音和播放功能&#xff0c;使用Swing创建图形用户界面&#xff0c;利用Java Sound API进行音频处理。下面是对此程序的详细剖析&#xff1a; 一、程序结构 程序主要由以下几个部分组成&#xff1a; RecorderFrm类&#xff1a;主框架类&#xff0c;继承自…...

OpenCV 图形API(26)图像滤波-----方框滤波函数boxFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 使用方框滤波器模糊图像。 该函数使用以下内核来平滑图像&#xff1a; K α [ 1 1 … 1 1 1 … 1 ⋮ ⋮ ⋱ ⋮ 1 1 … 1 ] K \alpha \begin{b…...

oracle 表空间(Tablespace)

在 Oracle 11g 中&#xff0c;表空间&#xff08;Tablespace&#xff09; 是数据库存储架构的核心逻辑单元&#xff0c;其原理基于 逻辑存储与物理存储的分离&#xff0c;通过分层管理数据文件、段&#xff08;Segment&#xff09;、区&#xff08;Extent&#xff09;和数据块&…...

Git 高级操作

Git不仅是代码管理的基石工具&#xff0c;更是开发者提升效率的瑞士军刀。掌握基础操作只是起点&#xff0c;真正的高手都在使用进阶技巧优化工作流。本文将深入解析Git四大高阶操作&#xff0c;助你轻松应对复杂开发场景&#xff01; 一、交互式暂存&#xff1a;精准控制提交粒…...

Go:程序结构

文章目录 名称声明变量短变量声明指针new 函数变量的生命周期 赋值多重赋值可赋值性 类型声明包和文件导入包初始化 作用域 名称 命名规则&#xff1a; 通用规则&#xff1a;函数、变量、常量、类型、语句标签和包的名称&#xff0c;开头须是字母&#xff08;Unicode 字符 &a…...

sqlserver2017 分离附加数据库

分离数据库 分离数据库是指将数据库从 SQL Server 实例中移除&#xff0c;但会完整保留数据库及其数据文件和事务日志文件。 然后可以使用这些文件将数据库附加到任何 SQL Server 实例&#xff0c;包括分离该数据库的服务器。 如果存在下列任何情况&#xff0c;则不能分离数据…...

QuarkPi-CA2 RK3588S卡片电脑:6.0Tops NPU+8K视频编解码+接口丰富,高性能嵌入式开发!

QuarkPi-CA2 RK3588S卡片电脑&#xff1a;6.0Tops NPU8K视频编解码接口丰富&#xff0c;高性能嵌入式开发&#xff01; 芯片框架 视频介绍 https://www.bilibili.com/video/BV1btdbYkEjY 开发板介绍 核心升级&#xff0c;产品炸裂 QuarkPi-CA2卡片电脑搭载瑞芯微RK3588S芯片…...

对称加密与非对称加密与消息摘要算法保证https的数据交互的完整性和保密性

一、对称加密与非对称加密的作用 1. 对称加密 作用&#xff1a; 保密性&#xff1a;对称加密使用相同的密钥对数据进行加密和解密&#xff0c;确保数据在传输过程中不被窃听。效率&#xff1a;对称加密算法&#xff08;如AES&#xff09;计算速度快&#xff0c;适合加密大量数…...

Lab Cloud FPGA 硬件在线实验云平台介绍

友晶科技依托其在FPGA技术领域的深厚积累&#xff0c;成功研发出了一套完整的FPGA云平台解决方案&#xff08;即FPGA 硬件在线实验云&#xff0c;简称LabCloud &#xff09;。LabCloud 是一个高效、实用的学习平台&#xff0c;目前已在多个学校成功部署。 LabCloud 是通过 B/S …...

相机回调函数为静态函数原因

在注册相机SDK的回调函数时&#xff0c;是否需要设置为静态函数取决于具体SDK的设计要求&#xff0c;但通常需要遵循以下原则&#xff1a; 1. 必须使用静态函数的情况 当相机SDK是C语言接口或要求普通函数指针时&#xff0c;回调必须声明为静态成员函数或全局函数&#xff1a;…...

实验室纯水器实验室超纯水机(常见类型、选型建议、维护保养)

不同实验室用水级别有何差异&#xff1f; 实验室用水级别由ASTM或ISO 3696等质量标准定义&#xff0c;有助于特定应用选择适合的水质。这些标准也考虑了生产成本&#xff0c;如1级(Type 1)超纯水的生产成本远高于2级(Type 2)或3级(Type 3)纯水。 1级超纯水 不含离子&#xff…...

腾讯云COS与ZKmall 开源商城的存储集成方案

ZKmall 开源商城与腾讯云对象存储&#xff08;COS&#xff09;的集成&#xff0c;可通过云端资源托管、自动化数据同步、高性能存储架构实现本地存储负载降低与访问效率提升。以下是基于搜索结果的集成路径与核心优化点&#xff1a; 一、存储架构升级&#xff1a;本地与云端协同…...

Python 深度学习实战 第3章 Keras和TensorFlowKeras 训练和评估模型实例

Python 深度学习实战 第3章 Keras和TensorFlow&Keras 训练和评估模型实例 内容概要 第3章介绍了Keras和TensorFlow的基本概念及其关系&#xff0c;并指导如何设置深度学习工作区。本章还概述了核心深度学习概念如何转化为Keras和TensorFlow API。通过本章&#xff0c;读者…...

基于SpringBoot的动物救助中心系统(源码+数据库)

500基于SpringBoot的动物救助中心系统&#xff0c;本系统共分为2个角色&#xff1a;系统管理员、用户&#xff0c;主要功能如下 【管理员】&#xff1a; 1. 登录&#xff1a;管理员可以通过登录系统来管理各种功能。 2. 用户管理&#xff1a;管理员可以查看用户列表&#xff0…...

【多模态大模型】《Qwen2.5-Omni》 论文解读

《Qwen2.5-Omni&#xff1a;重新定义端到端全模态大模型的技术范式》 论文解读 论文&#xff1a; https://arxiv.org/abs/2503.20215 &#xff08;2025.03.26&#xff09;代码&#xff1a; https://github.com/QwenLM/Qwen2.5-OmniNews&#xff1a; https://mp.weixin.qq.com/…...

go 通过汇编分析函数传参与返回值机制

文章目录 概要一、前置知识二、汇编分析2.1、示例2.2、汇编2.2.1、 寄存器传值的汇编2.2.2、 栈内存传值的汇编 三、拓展3.1 了解go中的Duff’s Device3.2 go tool compile3.2 call 0x46dc70 & call 0x46dfda 概要 在上一篇文章中&#xff0c;我们研究了go函数调用时的栈布…...

蓝桥杯C/C++省赛/国赛注意事项及运行环境配置

大佬的蓝桥杯考前急救指南 对拍&#xff08;手动生成测试数据&#xff09;代码&#xff1a; #include <bits/stdc.h> // 包含所有标准库的头文件 using namespace std; // 使用标准命名空间int main() {srand(time(0)); // 设置随机数种子为当前时间&#xff0c;确保每次…...

CSS高度坍塌?如何解决?

一、什么是高度坍塌&#xff1f; 高度坍塌&#xff08;Collapsing Margins&#xff09;是指当父元素没有设置边框&#xff08;border&#xff09;、内边距&#xff08;padding&#xff09;、内容&#xff08;content&#xff09;或清除浮动时&#xff0c;其子元素的 margin 会…...

redis的基本使用

简介 redis&#xff0c;Remote Dictionary Server&#xff0c;远程字典服务&#xff0c;一个基于内存的、存储键值对的数据库。redis是开源的&#xff0c;使用C语言编写。因为redis的数据是存储在内存中的&#xff0c;所以redis通常被用来做数据库的缓存 优点&#xff1a; re…...

【蓝桥杯】单片机设计与开发,第十二届

/*头文件声明区*/ #include <STC15F2K60S2.H>//单片机寄存器头文件 #include <init.h>//初始化底层驱动头文件 #include <led.h>//led,蜂鸣器,继电器底层驱动头文件 #include <key.h>//按键底层驱动头文件 #include <seg.h>//数码管底层驱动头…...

主流时序数据库深度对比:TDengine、InfluxDB与IoTDB的技术特性、性能及选型考量

目录 引言 一、 核心架构与技术特性对比 1.1、 TDengine&#xff1a;面向物联网的特定优化 1.2. InfluxDB&#xff1a;成熟的通用时序平台 1.3. Apache IoTDB&#xff1a;面向工业场景的精细化设计 二、 核心性能指标对比分析 2.1、写入性能 2.2、查询性能 三、 关键技…...

使用人工智能大模型腾讯元宝,如何免费快速做高质量的新闻稿?

今天我们学习使用人工智能大模型腾讯元宝&#xff0c;如何免费快速做高质量的新闻稿&#xff1f; 手把手学习视频地址&#xff1a;https://edu.csdn.net/learn/40402/666431 第一步在腾讯元宝对话框中输入如何协助老师做新闻稿&#xff0c;通过提问&#xff0c;我们了解了老师…...

国产Linux系统统信安装redis教程步骤

系统环境 uname -a Linux FlencherHU-PC 6.12.9-amd64-desktop-rolling #23.01.01.18 SMP PREEMPT_DYNAMIC Fri Jan 10 18:29:31 CST 2025 x86_64 GNU/Linux官网下载源码包并解压 下载链接 https://download.redis.io/releases/redis-7.0.15.tar.gz?_gl11h424d3_gcl_au*ODQ5…...

leetcode590 N叉树的后序遍历

前序遍历 的顺序是&#xff1a;根 → 子节点1 → 子节点2 → ... → 子节点N 后序遍历 的顺序是&#xff1a;子节点1 → 子节点2 → ... → 子节点N → 根 首先一个办法就是前序遍历结果进行翻转 在 迭代法 实现 后序遍历 时&#xff0c;如果采用 前序遍历 反转 的方式&…...

docker desktop 的安装和使用

一、Docker Desktop 是什么&#xff1f; Docker Desktop 是一款专为开发者设计的工具&#xff0c;可以在本地计算机&#xff08;Windows/macOS&#xff09;上快速运行和管理容器&#xff08;Container&#xff09;环境。以下是核心功能&#xff1a; 核心特点说明容器化开发基于…...

QCustomPlot频谱图

使用QCutomPlot做的读取txt文件显示频谱图的demo,帮助大家了解QCustomPlot的基本使用 1.运行结果 demo比较简单,用于文件读取,鼠标放大缩小,右键截图等基础功能. 2.绘图详解 绘图核心是将类提升为QCustomPlot之后进行重绘,重绘之前设计图表曲线,图标标题,坐标轴,坐标轴范围,背…...