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

编译和链接【四】链接详解

文章目录

  • 编译和链接【四】链接详解
    • 前言
    • 系列文章入口
    • 符号表和重定位表
    • 链接过程
      • 分段组装
      • 符号决议
      • 重定位

编译和链接【四】链接详解

前言

在我大一的时候, 我使用VC6.0对C语言程序进行编译链接和运行 , 然后我接触了VS, Qt creator等众多IDE, 这些IDE界面友好, 使用方便, 例如我最喜欢的VS,一键编译运行。对于大一的我,不需要了解编译的整个过程就可以运行,这无疑是非常棒的,并且增加了我对编程的兴趣,同时也简化了我后续的软件开发, 我只需要关心业务和功能代码即可。

但是今天, 我不想“逃课了”,欢迎来到我的频道,本系列 将会介绍编译中的一系列细节。

在正式开始之前,我要推荐两本书,一本是《程序员的自我修养》,另一本是《鲸书》,这两本书对编译的整个过程做了非常详细,非常完备的介绍,但是恰恰如此,我想很多时候,很多知识在工作上是用不到的,也许这句话在很多年多的我会反驳,但是站在工作一年的现在,我将会给你介绍,我所了解的编译和链接。

系列文章入口

关注我~持续更新

编译和链接【一】总述

编译和链接【二】预处理

编译和链接【三】编译过程

符号表和重定位表

在链接过程中,符号表和重定位表是非常重要的两个表。在汇编阶段,汇编器会分析汇编语言中各个section的信息,收集各种符号,生成符号表,将符号在section内的偏移地址也填充到符号表里。

使用 readelf -s main.o 查看目标文件的符号表信息

在这里插入图片描述

在符号表里,可以看到许多符号信息,比如符号的地址,类型和占用空间的大小。

符号表本质上一个结构体数组,在Arm平台下,定义在Linux内核的/arch/arm/include/asm/elf.h里

typedef struct elf32_sym
{Elf32_word st_name;Elf32_Addr st_value;Elf32_word st_size;unsigned char st_info;unsigned cahr st_other;Elf32_Half st_shndx;
}

符号的类型主要有:

  • OBJECT:对象类型,一般用来标识变量
  • FUNC:函数
  • FILE:当前目标文件的名称
  • SECTION:代表一个section,用来重定位
  • COMMON:公用块数据对象,是一个全局弱符号,在当前文件中未分配空间
  • TLS:表示该符号对应的变量存储在线程局部存储

在 C/C++中,编译器是是源文件为翻译单元进行编译的,如果在我们的程序中,我们引用了其他文件的函数或者全局变量,那么编译器会不会报错呢?

其实是不会的,只要你在调用之前进行声明,那么编译器就会认为你的这个函数或者全局变量在其他文件中定义,编译阶段是不会报错的,链接器会尝试在其他文件或者库里查找这个符号的具体定义,但是如果此时还没找到,那么就会报连链接错误。

main.cpp:undefined reference to ‘Addr’

编译器在给每个目标文件生成符号表的过程中,如果没用找到符号的定义,那么也会把这些符号搜集在一起并保存到一个单独的符号表中,这个符号表就是重定位符号表

使用 readelf -s main.o 查看目标文件的符号表信息

在这里插入图片描述

在这个表的Type列,类型为NOTYPE属于未定义状态,需要后续填充,同时在main.o中会使用一个重定位表**.rel.text**来记录这些需要重定位的符号。使用readelf查看重定位表和section header table信息

readelf -S main.o # 查看section header table信息

readelf -r main.o # 查看重定位信息

可以看到:

Relocation section '.rela.text' at offset 0x4c0 contains 2 entries:Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000004  000200000002 R_X86_64_PC32     0000000000000000 printf - 4
00000000000c  000300000002 R_X86_64_PC32     0000000000000000 puts - 4

我们看到了需要重定位的符号:printf和puts,在后续的链接过程中经过重定位,会更新为新的实际地址

链接过程

在前面的文章里,我介绍了目标文件是由:代码段,数据段,BSS段,符号表等section组成的,这些section从目标文件的零地址处开始顺序排放,而每个符号相对于零地址的偏移,就是每个符号的地址,但是这个地址是暂时的。

在后续的链接过程中,这些目标文件的section会重新拆分组装,每个section的起始参考地址会发生变化,导致每个section定义的函数、全局变量等符号的地址也随之变化,需要重新修改,即:重定位

这些函数、变量等符号被编译器收集并放在符号表,符号表又被放在目标文件中,这些目标文件是不可指定的,它们需经过链接器链接、重定位才能运行。

而整个链接过程主要分为三步:

  • 分段组装
  • 符号决议
  • 重定位

分段组装

顾名思义,在链接的第一步就是将各个目标文件重新分解组装,代码段放在一起,形成最终可执行文件的代码段,其他的section也是如此。

在这里插入图片描述

而需要特别关注的section就是符号表,链接器会在可执行文件里创建一个全局的符号表。通过这步操作,一个可执行文件的所有符号都有的自己的地址,并保存在全局符号表中,但是此时全局符号表的地址还是原来在各个目标文件中的地址,即:相对于零地址的偏移。

显然,当前的任务是需要修改这个地址,而需要确定这个地址,就需要先明白,可执行文件最终是要被加载到内存中执行的,那么会被加载到什么地址呢?

一般来说,会在链接时,指定一个链接地址,链接地址也是程序要加载到内存中的地址。

各个段在可执行文件中先后组装顺序也要是一个需要考量的问题。这个问题一般是通过链接脚本来解决。

链接脚本本质上是一个脚本文件,在这个文件里,不仅规定了各个段的组装顺序、起始地址、位置对齐信息,同时对输出的可执行格式、运行平台、入口地址都有描述。

链接器就是根据链接脚本的规则来组装可执行文件的,并最终将这些信息以section的形式保存在可执行文件的ELF Header中。

下面展示一个简单的链接脚本:

OUTPUT_FORMAT("elf32-littlearm") ;输出ELF文件格式
OUTPUT_ARCH("ARM")	; 运行在arm平台
ENTRY(_start) ;程序入口地址
SECTIONS
{.= 0x60000000 	; 代码段的起始地址.text: {*(.text)}	; 代码段.= 0x6020000	; 数组段起始地址.data: {*(data)}	; 数据段.bss: {*(.bss)}	; BSS段
}

程序运行时,加载器首先会解析可执行文件中的ELFHeader头部信息,验证程序的运行平台和加载地址信息,然后将可执行文件加载到内存中对应的地址,程序就可以正常运行了。

使用ld --verbose来查看链接器默认的链接脚本

在这里插入图片描述

不同的编译器默认的链接地址也是不一样的,在一个由带有MMU的系统中,程序的链接起始地址往往都是一个虚拟地址,程序运行过程中还需要地址转换,通过MMU将虚拟地址转换为物理地址,然后才能访问内存,这部分内容属于CPU硬件底层要关心的内容,和编译原理是不冲突的。

符号决议

当我们在翻译单元里,统一了相同命名的符号的时候,就会发生符号冲突,那么最终的可执行文件会使用哪一个呢?

这就是符号决议的内容,一般规则为:

  • 强符号不能相同命名
  • 强符号可以和弱符号共存
  • 弱符号可以共存。

函数名,初始化的全局变量就是强符号,而未初始化的全局变量则是弱符号。

在一个工程项目里,强符号不能多次定义,否则就会发生重定义错误,而强符号和弱符号可以共存,当共存时,强符号会覆盖弱符号,链接器会选择强符号作为可执行文件的最终符号。

main.c

#include <stdio.h>int Addr;int main()
{int a = 3, b = 4;int c = a + b;printf("Addr=%d\n", Addr);return 0;
}

source.c

int Addr = 1;

使用gcc source.c main.c则可通过编译

链接器在进行符号决议时,选择了强符号(source.c源文件中定义的i符 号),丢弃了弱符号(main.c源文件中定义的未初始化的全局符号i)。如果修改程序,将main.c文件中的Addr也赋一个初值,再去重新编译这两个源文件,就会发现链接器会报重定义错误,因为此时一个项目中出现了两个同名的强符号。

在这里插入图片描述

当然,这段代码在C++中是无法通过编译的,C++对弱符号的定义有所不同,如果此时Addr声明为extern,则可以通过编译。

链接器也允许一个项目中出现多个弱符号共存。在程序编译期间,编译器在分析每个文件中未初始化的全局变量时,并不知道该符号在链接阶段是被采用还是被丢弃,因此在程序编译期间,未初始化的全局变量并没有被直接放置在BSS段中,而是将这些弱符号放到一个叫作COMMON的临时块中,在符号表中使用一个未定义的COMMON来标记,在目标文件中也没有给它们分配存储空间。

在链接期间,链接器会比较多个文件中的弱符号,选择占用空间最大的那一个,作为可执行文件中的最终符号,此时弱符号的大小已经确定,并被直接放到了可执行文件的BSS段中。

main.c

#include <stdio.h>char Addr;int main()
{int a = 3, b = 4;int c = a + b;return 0;
}

source.c

double Addr = 1;

在这里插入图片描述

在main.c里,我将Addr定义为char类型,而source.c里,我定义为double类型,在我的电脑上,double类型占8个字节,那么可以在目标文件里看到实际大小为8个字节,但是在source.o这个目标文件里,可以看到大小为1个字节。

但是最终生成的可执行目标文件的大小为8个字节,符合我说的结论。

如果在项目中有特殊需求,我们也可以将一些强符号显式转化为弱符号。GNU C编译器在ANSI C语法标准的基础上扩展了一系列C语言语法,如提供了一个__attribute__关键字用来声明符号的属性。通过下面的命令,可以将一个强符号转化为弱符号。

_attribute_((weak)) int n = 100;

_attribut_((weak)) void func();

下面进行验证:

main.c

#include <stdio.h>__attribute__((weak)) int Addr = 20;int main()
{printf("Addr = %d\n", Addr);return 0;
}

source.c

int Addr = 10;

在这里插入图片描述

现在在C/C++中,都能通过编译了。

和强符号、弱符号对应的,还有强引用、弱引用的概念。在一个程序中,我们可以定义多个函数和变量,变量名和函数名都是符号,这些符号的本质,或者说这些符号值,其实就是地址。在另一个文件中,我们可以通过函数名去调用该函数,通过变量名去访问该变量。 我们通过符号去调用一个函数或访问一个变量,通常称之为引用(reference),强符号对应强引用,弱符号对应弱引用。

在程序链接过程中,若对一个符号的引用为强引用,链接时找不到其定义,链接器将会报未定义错误;若对一个符号的引用为弱引用,链接时找不到其定义,则链接器不会报错,不会影响最终可执行文件的生成。可执行文件在运行时如果没有找到该符号的定义才会报错。

利用链接器对弱引用的处理规则,我们在引用一个符号之前可以先判断该符号是否存在(定义)。这样做的好处是:当我们引用一个未定义符号时,在链接阶段不会报错,在运行阶段通过判断运行,也可以避免运行错误。

举个例子:我们想实现一个加法模块,并封装成库的形式给应用程序开发者调用,在模块实现的过程中,我们可以将提供给用户的一系列API函数声明为弱符号。

这样做的好处就是:

  • 当我们对某些API的实现不满意的时候,我们可以定义和其同名的函数,这样直接调用不会发生冲突
  • 在库的实现过程中,我们可以将某些还没完成的API定义为弱引用,应用程序在调用之前先判断该函数是否实现,然后才调用,这样,在未来发布新版本的时候,无论这些函数是否实现或者已经删除,都不会影响应用程序的正常链接和运行。

例如:

header.h

#pragma once__attribute__((weak)) int add(int a, int b);

source.c

#include "header.h"__attribute__((weak)) int add(int a, int b )
{return a + b;
}

main.c

#include <stdio.h>
#include "header.h"__attribute__((weak)) int Addr = 20;int main()
{if (add)printf("add(1, 2) = %d\n", add(1, 2));return 0;
}

在上面的代码片里,我们实现了一个加法库,并把接口声明为弱引用,而在main.c里,我们调用了add函数,但是在调用之前,我们先判断了符号这样做的好处就是无论程序是否存在都不影响运行。

在这里插入图片描述

在这里插入图片描述

程序的运行结果也从侧面验证了上面的理论分析是正确的。

重定位

经过符号决议,我们解决了链接过程中多文件符号冲突的问题。经过处理之后,可执行文件的符号表中的每个符号虽然都确定下来了,但是还存在一个问题:符号表中的每个符号值,也就是每个函数、全局变量的地址,还是原来各个目标文件中的值,还都是基于零地址的偏移。链接器将各个目标文件重新分解组装后,各个段的起始地址都发生了变化。

那么各个段中的符号地址也要跟着发生变化。编译器生成的各个目标文件,以零地址为起始地址放置各个函数的指令代码,各个函数相对于零地址的偏移就是各个函数的入口地址。

链接器在链接程序时一般会基于某个链接地址link_addr进行链接,所以最后main()函数和sub()函数的真实地址就被改变了

程序经过重新分解组装后,无论是代码段,还是数据段,各个符号的真实地址都发生了变化。而此时可执行文件的全局符号表中,各个符号的值还是原来的地址,所以接下来还要修改全局符号表中这些符号的值,将它们的真实地址更新到符号表中。修改完毕后,当我们想通过符号引用去调用一个函数或访问一个变量时,就能找到它们在内存中的真实地址了。

在这里插入图片描述

链接器怎么知道哪些符号需要重定位呢?不要忘了,在各个目标文件中还有一个重定位表,专门记录各个文件中需要重定位的符号。重定位的核心工作就是修正指令中的符号地址,是链接过程中的最后一步,也是最核心、最重要的一步,前面两步的操作,其实都是为这一步服务的。

在编译阶段,编译器在将各个C源文件生成目标文件的过程中,遇到未定义的符号一般不会报错,编译器会认为这些符号可能会在其他地方定义。在链接阶段,链接器在其他地方找不到该符号的定义,才会报链接错误。编译器在链接阶段会搜集这些未定义的符号,生成一个重定位表,用来告诉链接器,这些符号在文件中被引用,但是在本文件中没有找到定义,有可能在其他文件或库中定义,“我就先不报错了,你链接的时候找找看”。

无论是代码段,还是数据段,只要这个段中有需要重定位的符号 , 编 译 器 都 会 生 成 一 个 重 定 位 表 与 其 对 应 : .rel.text或.rel.data。这些重定位表记录各个段中需要重定位的各种符号,并以section的形式保存在各个目标文件中。我们可以通过readelf或objdump命令来查看一个目标文件中的重定位表信息。

重定位表中有一个信息比较重要:需要重定位的符号在指令代码中的偏移地址offset,链接器修正指令代码中各个符号的值时要根据这个地址信息才能从茫茫的二级制代码中找到它们。链接器读取各个目标文件中的重定位表,根据这些符号在可执行文件中的新地址,进行符号重定位,修改指令代码中引用这些符号的地址,并生成新的符号表。重定位过程中的地址修正其实很简单,如下所示。

重定位的新地址 = 新的段基址 + 段内偏移

至此,整个链接过程就结束了,我们跟踪的整个编译流程也就结束了。最终生成的文件就是一个可执行目标文件。

相关文章:

编译和链接【四】链接详解

文章目录 编译和链接【四】链接详解前言系列文章入口符号表和重定位表链接过程分段组装符号决议重定位 编译和链接【四】链接详解 前言 在我大一的时候&#xff0c; 我使用VC6.0对C语言程序进行编译链接和运行 &#xff0c; 然后我接触了VS&#xff0c; Qt creator等众多IDE&…...

C语言进阶——4自定义类型(2)— 位段/枚举/联合体

目录 2. 位段2.1 什么是位段2.2 位段的内存分配2.3 位段的跨平台问题2.4 位段的应用 3. 枚举3.1 枚举类型的定义3.2 枚举的优点3.3 枚举的使用 4. 联合&#xff08;共用体&#xff09;4.1 联合类型的定义4.2 联合的特点4.3 联合大小的计算 2. 位段 2.1 什么是位段 位段的声明…...

企业级高可用 Kubernetes 实践:基于青云 LB 搭建容灾与负载均衡集群全攻略

一、前言 在企业生产环境,k8s高可用是一个必不可少的特性,其中最通用的场景就是如何在 k8s 集群宕机一个节点的情况下保障服务依旧可用。部署高可用k8s集群对于企业级云平台来说是一个根本性的原则,容错、服务可用和数据安全是高可用基础设施的关键。本文是在青云上利用青云…...

250213-异常exception

1. 概念 异常的抛出&#xff08;throw&#xff09;&#xff1a;若在方法运行中出现错误&#xff0c;则方法会生成代表该异常的一个对象&#xff0c;并把它交给运行时系统&#xff0c;这个过程叫做抛出。 异常的捕获&#xff08;catch&#xff09;&#xff1a;运行时系统接收到…...

MySQL - 索引 - 介绍

索引(Index)是帮助数据库高效获取数据的数据结构. 结构 语法 创建索引 creat [unique] index 索引名 on 表名 (字段名, ...); //创建唯一索引时加上unique, 多个字段用逗号隔开 查看索引 show index from 表名; 删除索引 drop index 索引名 on 表名;...

每日一题——90. 子集 II

题目链接&#xff1a;90. 子集 II - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; class Solution { private:vector<vector<int>> result;vector<int> path;void traversal(vector<int>& nums,int startindex,vector<bool> …...

Mysql进阶篇(mysqlcheck - 表维护程序)

mysqlcheck的作用 mysqlcheck客户端用于执行表维护&#xff0c;可以对表进行&#xff1a;分析、检查、优化或修复操作。 &#xff08;1&#xff09;分析的作用是查看表的关键字分布&#xff0c;能够让 sql 生成正确的执行计划&#xff08;支持 InnoDB&#xff0c;MyISAM&#x…...

ChartDB:一个基于Web的可视化数据库设计工具

这次给大家介绍一个可视化的数据库设计工具&#xff1a;ChartDB。 ChartDB 是一个免费开源的数据库可视化设计工具&#xff0c;支持的数据库包括 MySQL、MariaDB、PostgreSQL、Microsoft SQL Server、SQLite、ClickHouse 等。 对于已有的数据库&#xff0c;ChartDB 提供了一键…...

Java NIO基础与实战:如何提升IO操作性能

Java NIO 概述 Java NIO&#xff08;新 I/O&#xff09;是 Java 提供的一个更为高效的 I/O 处理框架。Java NIO&#xff08;New I/O&#xff09;是对传统 I/O&#xff08;java.io&#xff09;模型的改进&#xff0c;它引入了非阻塞 I/O 操作和面向缓冲区的数据读写方式&#x…...

Elasticsearch:同义词在 RAG 中重要吗?

作者&#xff1a;来自 Elastic Jeffrey Rengifo 及 Toms Mura 探索 RAG 应用程序中 Elasticsearch 同义词的功能。 同义词允许我们使用具有相同含义的不同词语在文档中搜索&#xff0c;以确保用户无论使用什么确切的词语都能找到他们所寻找的内容。你可能会认为&#xff0c;由于…...

Python - Python正则表达式

正则表达式&#xff08;Regular Expression&#xff09;&#xff0c;又称规则表达式。正则表达式&#xff08;Regular Expression&#xff09;是一组由字母和符号组成的特殊文本&#xff0c;用于从文本中找出满足特定格式的句子。正则表达式通常被用来检索、替换那些符合某个模…...

DeepSeek 指导手册(入门到精通)

第⼀章&#xff1a;准备篇&#xff08;三分钟上手&#xff09;1.1 三分钟创建你的 AI 伙伴1.2 认识你的 AI 控制台 第二章&#xff1a;基础对话篇&#xff08;像交朋友⼀样学交流&#xff09;2.1 有效提问的五个黄金法则2.2 新手必学魔法指令 第三章&#xff1a;效率飞跃篇&…...

Android adb测试常用命令大全

目录 一、查看最上层成activity名字: 二、查看Activity的任务栈&#xff1a; 三、获取安装包信息 四、性能相关 1、显示CPU信息 : 2、查看CPU使用信息 3、内存信息&#xff08;meminfo package_name or pid 使用程序的包名或者进程id显示内存信息&#xff09; 4、电量信…...

【python语言应用】最新全流程Python编程、机器学习与深度学习实践技术应用(帮助你快速了解和入门 Python)

近年来&#xff0c;人工智能领域的飞速发展极大地改变了各个行业的面貌。当前最新的技术动态&#xff0c;如大型语言模型和深度学习技术的发展&#xff0c;展示了深度学习和机器学习技术的强大潜力&#xff0c;成为推动创新和提升竞争力的关键。特别是PyTorch&#xff0c;凭借其…...

在不知道进程的情况下怎么关闭

在不知道具体进程ID&#xff08;PID&#xff09;或者进程可能会变动的情况下&#xff0c;关闭MinIO服务器的方法通常依赖于你如何启动MinIO以及你的操作系统环境。以下是一些建议的步骤&#xff1a; 1. 使用系统服务管理工具 如果你将MinIO配置为系统服务&#xff08;例如在L…...

算力平台 驱动云的使用

驱动云的使用 1 进入官网注册2 上传数据3 上传模型4 创建项目5 开发环境6 停止使用 1 进入官网注册 点击这个进入 可以看到注册之后送十个算力点 如果不训练&#xff0c;仅仅上传数据和模型&#xff0c;那么也是要收费的&#xff0c;因为存储数据要占用驱动云的空间。 2 上…...

高校LabVIEW开发调试中的常见问题

在高校进行LabVIEW开发调试时&#xff0c;常常面临硬件选型不当、方案设计不合理、布线不专业以及人员流动性强等问题。这些问题可能影响项目的进展和质量。本文将总结这些问题&#xff0c;并给出具体的解决方案&#xff0c;帮助学生和团队更高效地开展开发工作。 ​ 1. 硬件选…...

数据结构——结构体位域、typedef类型重定义、宏、共用体union、枚举、虚拟内存划分

一、结构体位域 1.1 结构体位域的基础 结构体位域&#xff1a;把结构体字节大小扣到极致的一个类型&#xff0c;以bit单位 格式&#xff1a;struct 位域体名{数据类型 位域名:位域大小;数据类型 位域名:位域大小;...};解析&#xff1a;位域体名&#xff1a;可有可无&#xff…...

git bash删除库中的分支与文件

一、 在 GitHub 上删除非 main 分支的步骤可以分为两部分&#xff1a;首先在本地删除该分支&#xff0c;然后在 GitHub 上删除远程分支。以下是详细的步骤&#xff1a; 1. 删除远程分支&#xff08;在 GitHub 上删除&#xff09; 打开 GitHub 仓库页面&#xff0c;进入你的仓…...

连锁收银系统的核心架构与技术选型

在连锁门店的日常运营里&#xff0c;连锁收银系统扮演着极为重要的角色&#xff0c;它不仅承担着交易结算的基础任务&#xff0c;还关联着库存管理、会员服务、数据分析等多个关键环节。一套设计精良的核心架构与合理的技术选型&#xff0c;是保障收银系统高效、稳定运行的基础…...

称呼计算器:智能科技,简化您的计算生活

一款手机应用程序&#xff0c;安卓设备上使用。这款计算器应用以其简洁的界面、实用的功能和良好的用户体验而受到用户的喜爱。 计算器的主要特点包括&#xff1a; 基本计算功能&#xff1a;支持加、减、乘、除等基本运算。 科学计算器模式&#xff1a;提供更高级的数学运算功…...

qt的QMainWindow保存窗口和恢复窗口状态

保存窗口状态 QSettings settings("MyCompany", "MyApp"); // 指定存储的应用信息 settings.setValue("mainWindowState", saveState());saveState() 返回一个 QByteArray&#xff0c;包含 所有停靠窗口和工具栏的状态。QSettings 用于存储数据…...

【mysql】记一次mysql服务挂了后的数据恢复过程

现象 服务器异常&#xff0c;导致mysql服务异常退出&#xff0c;重启后&#xff0c;校验redo log异常 说明 mysql服务是通过docker-compose启动的,serviceName是db磁盘挂载&#xff1a;/var/lib/mysql挂载到本地磁盘/data/mysql 处理过程 备份 查看磁盘挂载列表 docker …...

使用 LangChain 对接硅基流动(SiliconFlow)API:构建一个智能对话系统

文章目录 什么是硅基流动&#xff08;SiliconFlow&#xff09;&#xff1f;LangChain 简介在 LangChain 中对接硅基流动步骤 1&#xff1a;安装必要的库步骤 2&#xff1a;设置 API 密钥步骤 3&#xff1a;编写代码代码解析步骤 4&#xff1a;运行代码如何扩展和改进总结 在现代…...

K8s 证书认知(K8s Certificate Awareness)

K8s 证书认知 在谈起 Kubernetes 证书时&#xff0c;总感觉其涵盖的内容繁多&#xff0c;仿佛千头万绪&#xff0c;让人不知该从何处着手阐述。为了更好地理清思路&#xff0c;本文将对相关内容进行系统的梳理和记录。 1、证书及链路关系 Kubeadm部署的集群&#xff0c;K8s …...

iperf

iperf 是一个网络性能测试工具&#xff0c;用于测量TCP和UDP的网络带宽。-c 参数表示客户端模式&#xff0c;用于指定要连接的服务器地址。以下是一些常见的 iperf 客户端命令示例&#xff1a; 基本用法 iperf -c <server_ip> <server_ip>&#xff1a;服务器的IP…...

【FastAPI 使用FastAPI和uvicorn来同时运行HTTP和HTTPS的Python应用程序】

在本文中&#xff0c;我们将介绍如何使用 FastAPI和uvicorn来同时运行HTTP和HTTPS的 Python应用程序。 简介 FastAPI是一个高性能的Web框架&#xff0c;可以用于构建快速、可靠的API。它基于Python的类型提示和异步支持&#xff0c;使得开发者可以轻松地编写出安全且高效的代…...

Windows系统安装搭建悟空crm客户管理系统 教程

1、在安装悟空 CRM 之前&#xff0c;需要确保你的 Windows 系统上已经安装了以下软件&#xff1a; Web 服务器&#xff1a;推荐使用 Apache 或 Nginx&#xff0c;这里以 Nginx 为例。你可以使用集成环境套件如 XAMPP 来简化安装过程&#xff0c;它包含了 Nginx 、MySQL、PHP 等…...

使用API有效率地管理Dynadot域名,清除某一文件夹中域名的默认DNS设置

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…...

评估多智能体协作网络(MACNET)的性能:COT和AUTOGPT基线方法

评估多智能体协作网络(MACNET)的性能 方法选择:选择COT(思维链,Chain of Thought)、AUTOGPT等作为基线方法。 COT是一种通过在推理过程中生成中间推理步骤,来增强语言模型推理能力的方法,能让模型更好地处理复杂问题,比如在数学问题求解中,展示解题步骤。 AUTOGPT则是…...

(4/100)每日小游戏平台系列

新增一个点击反应速度测试&#xff01; 点击反应速度测试是一款简单有趣的网页小游戏&#xff0c;旨在测试玩家的反应能力和专注度。通过随机高亮的颜色块&#xff0c;玩家需要快速点击正确的颜色&#xff0c;并在限定时间内挑战自己的反应速度。 &#x1f4dc; 游戏规则 游戏开…...

Day42(补)【AI思考】-编译过程中语法分析及递归子程序分析法的系统性解析

文章目录 编译过程中语法分析及递归子程序分析法的系统性解析**一、总览&#xff1a;编译流程中的语法分析****1. 编译过程核心步骤** **二、语法分析的核心任务****1. 核心目标****2. 现实类比** **三、递归子程序分析法的本质****1. 方法分类****2. 递归子程序分析法的运作原…...

AcWing 190. 字串变换 --BFS-双向搜索

已知有两个字串 A, B 及一组字串变换的规则&#xff08;至多 66 个规则&#xff09;: A1→B1 A2→B2 … 规则的含义为&#xff1a;在 A 中的子串 A1A1 可以变换为 B1、A2 可以变换为 B2…。 例如&#xff1a;A&#xff1d;abcd B&#xff1d;xyz 变换规则为&#xff1a; …...

visual studio导入cmake项目后打开无法删除和回车

通过Cmakelists.txt导入的项目做删除和回车无法响应&#xff0c;需要点击项目&#xff0c;然后选择配置项目就可以了...

【论文笔记】ZeroGS:扩展Spann3R+GS+pose估计

spann3r是利用dust3r做了增量式的点云重建&#xff0c;这里zeroGS在前者的基础上&#xff0c;进行了增量式的GS重建以及进行了pose的联合优化&#xff0c;这是一篇dust3r与GS结合的具有启发意义的工作。 abstract NeRF和3DGS是重建和渲染逼真图像的流行技术。然而&#xff0c;…...

Vue2中常用指令

文章目录 Vue2中常用指令1. v-text 动态渲染纯文本内容1. 作用2. 基本用法3. 示例4. 注意事项 2. v-html 动态渲染 HTML 内容1. 作用2. 基本用法3. 示例4. 注意事项 3. v-bind 动态绑定 HTML 属性1. 作用2. 基本用法3. 示例4. 注意事项5. 绑定class属性的用法6. 绑定style属性的…...

09-轮转数组

给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 方法一&#xff1a;使用额外数组 function rotate(nums: number[], k: number): void {const n nums.length;k k % n; // 处理 k 大于数组长度的情况const newNums new A…...

本地Deepseek-r1:7b模型集成到Google网页中对话

本地Deepseek-r1:7b网页对话 基于上一篇本地部署的Deepseek-r1:7b&#xff0c;使用黑窗口对话不方便&#xff0c;现在将本地模型通过插件集成到Google浏览器中 安装Google插件 在Chrome应用商店中搜索page assis 直接添加至Chrome 修改一下语言 RAG设置本地运行的模型&#…...

算法——结合实例了解广度优先搜索(BFS)搜索

一、广度优先搜索初印象 想象一下&#xff0c;你身处一座陌生的城市&#xff0c;想要从当前位置前往某个景点&#xff0c;你打开手机上的地图导航软件&#xff0c;输入目的地后&#xff0c;导航软件会迅速规划出一条最短路线。这背后&#xff0c;就可能运用到了广度优先搜索&am…...

2025年3月营销灵感日历

2025年的第一场营销大战已经拉开帷幕了&#xff01; 三月可是全年最值钱的营销黄金月——妇女节、植树节、315消费者日三大爆点连击&#xff0c;还有春分、睡眠日、世界诗歌日等20隐藏流量密码。 道叔连夜扒了18个行业数据&#xff0c;整理了这份《2025年3月营销灵感日历》&a…...

【认证授权FAQ】SSL/TLS证书过期导致的CLS认证失败

问题现象 问题分析 属于Agent操作系统的根认证机构过期问题&#xff0c;需要下载CA然后在系统安装。 DigiCert根证书和中间证书将在未来几年过期&#xff0c;一旦证书过期&#xff0c;基于证书颁发的SSL/TLS证书将不再信任&#xff0c;导致网站无法HTTPs访问。需要迁移到新的根…...

飞书专栏-TEE文档

CSDN学院课程连接&#xff1a;https://edu.csdn.net/course/detail/39573...

自己部署 DeepSeek 助力 Vue 开发:打造丝滑的时间线(Timeline )

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 自己…...

机器学习:集成学习和随机森林

集成学习 集成学习通过构建并合并多个模型来完成学习,从而获得比单一学习模型更显著优越的泛化能力,集成学习就是利用模型的"集体智慧",提升预测的准确率,根据单个模型方式,集成学习可分为两大类: 个体之间存在强依赖关系,其代表为Boosting算法个体之间不存在强依赖…...

力扣刷题(数组篇)

日期类 #pragma once#include <iostream> #include <assert.h> using namespace std;class Date { public:// 构造会频繁调用&#xff0c;所以直接放在类里面&#xff08;类里面的成员函数默认为内联&#xff09;Date(int year 1, int month 1, int day 1)//构…...

Jenkins 新建配置 Freestyle project 任务 六

Jenkins 新建配置 Freestyle project 任务 六 一、新建任务 在 Jenkins 界面 点击 New Item 点击 Apply 点击 Save 回到任务主界面 二、General 点击左侧 Configure Description&#xff1a;任务描述 勾选 Discard old builds Discard old builds&#xff1a;控制何时…...

5.8 软件质量与软件质量保证

文章目录 软件质量模型软件质量保证 软件质量模型 软件质量模型有ISO/IEC9126&#xff0c;McCall。 ISO/IEC9126从功能性、可靠性、易使用性、效率、可维护性、可移植性这6个方面对软件质量进行分析。功能性包含适合性、依从性、准确性、安全性、互用性。可靠性包含成熟性、容错…...

二次封装axios解决异步通信痛点

为了方便扩展,和增加配置的灵活性,这里将通过封装一个类来实现axios的二次封装,要实现的功能包括: 为请求传入自定义的配置,控制单次请求的不同行为在响应拦截器中对业务逻辑进行处理,根据业务约定的成功数据结构,返回业务数据对响应错误进行处理,配置显示对话框或消息形…...

Flutter项目试水

1基本介绍 本文章在构建您的第一个 Flutter 应用指导下进行实践 可作为项目实践的辅助参考资料 Flutter 是 Google 的界面工具包&#xff0c;用于通过单一代码库针对移动设备、Web 和桌面设备构建应用。在此 Codelab 中&#xff0c;您将构建以下 Flutter 应用。 该应用可以…...

Java 大视界 -- 边缘计算与 Java 大数据协同发展的前景与挑战(85)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...