[Linux]从零开始的vs code交叉调试arm Linux程序教程

一、前言

        最近的项目中需要集成rknn的视觉识别,在这之前我并且没有将rknn集成到自己项目的经验。这里我需要在rknn原本demo的基础上我还需要集成自己的业务代码。但是又有一个问题,原本rknn我们都是使用交叉编译编译到开发板上的,并且我们还要再demo的基础上进行修改,这么多代码如果不能调试的话,那实现功能还是有一点困难了。后面找到了一种交叉调试的方法,总的来说就是,通过在X86的主机上交叉编译ARM的程序,然后将编译出来的二进制文件发送到开发板中,然后通过网络在X86的主机上交叉调试这个程序。通过网络交叉调试也是目前最主流的调试方式。那么本次教程,就来教大家如何使用vs code交叉调试arm linux中的程序,如果你准备好了,就让我们开始吧!

二、谁适合本次教程

        本次教程已经涉及到了Linux C应用开发部分了,所以并不适用于完全没有基础的小白,还请看本次教程的小伙伴具备一定的Linux基础和C语言基础。需要大家了解基本的Linux操作,理解交叉编译的概念。这里我会默认大家有基础,很多细节我并不会说或者是一笔带过。现在让我们开始吧!

三、交叉编译器的安装

        这里我们需要在X86的设备上编译ARM的程序就需要使用到交叉编译器,这里我们说的交叉指的就是架构交叉。所以第一步就需要我们安装一个交叉编译器。因为我们是编译ARM Linux的程序,所以这里也必须要在X86的Linux系统中进行编译,这也是为了保证链接的库都是Linux的,不会出现怪异的问题。

这里X86一侧的Linux系统,我们可以选择直接将Linux系统装到我们的电脑中,具体可以看下面的教程:

在物理机中安装Ubuntu:[Linux]如何在物理机安装Ubuntu(小白向)-CSDN博客

这里我们也可以选择将Linux安装到虚拟机中,我在教程中也会使用这种方式,具体可以看下下面的教程:

在虚拟机中安装Ubuntu:[Linux]如何在虚拟机安装Ubuntu?(小白向)_虚拟机 ubuntu-CSDN博客

我在教程中使用的Linux发行版为Ubuntu22.04,在虚拟机中安装Ubuntu的教程在上面给出的教程中已经讲得很详细了,大家直接参考即可。当然,这里也建议大家和我使用同样版本的系统,避免出现奇怪的问题。这里我就默认大家已经安装好了Ubuntu,如下图所示:

这里我们首先需要在终端中使用下面的命令更新一下软件包:

sudo apt update

这里我们安装两个软件包,分别是“openssh-server”和“net-tools”。安装这两个是为了方便我们查看虚拟机的IP地址以及方便我们进行SSH,相信各位Linux大神对此都不陌生,这里就不细说了,直接使用下面的命令安装即可:

sudo apt install openssh-server net-tools

这里安装完成以后,我们就可以通过“ifconfig”命令查看虚拟机的IP地址:

这里大家记住自己虚拟机的IP地址,后面要考的。

现在我们可以来下载一下交叉编译器的压缩包,这里我们直接使用下面的命令拉取即可。这里需要注意,我提供了两种ARM架构的交叉编译器,大家需要根据自己开发板芯片的架构进行选择,这里我们在开发板的终端中输入下面的命令就可以看到开发板的架构了:

uname -m

这里可以看到,我的开发板架构为“aarch64”也就是我们常说的arm64架构:

所以我这里就需要aarch64的交叉编译器。这里非常简单,就不多说了:

aarch64交叉编译器下载:

wget https://releases.linaro.org/components/toolchain/binaries/6.3-2017.05/aarch64-linux-gnu/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz

armhf交叉编译器下载:

wget  https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz?revision=e09a1c45-0ed3-4a8e-b06b-db3978fd8d56&rev=e09a1c450ed34a8eb06bdb3978fd8d56&hash=9C4F2E8255CB4D87EABF5769A2E65733- armhf-uclibcgnueabihf(RV1103/RV1106): https://console.zbox.filez.com/l/H1fV9a (fetch code: rknn)

因为我的开发板是64位的所以这里就选择了“aarch64”的交叉编译器,我们直接在终端中输入命令并且回车即可,随后就会进入下载:

如果你在这里被提示wget命令找不到之类的,可以使用下面的命令安装一下wget:

sudo apt install wget

当我们下载完交叉编译器以后,就会在当前目录看到一个交叉编译器的压缩包:

这里我们直接使用下面的命令对压缩包进行解压,这里我解压的是aarch64的压缩包,所以命令这样写,如果你的交叉编译器是armhf请自己修改一下命令:

tar -xvf gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz

回车以后,解压就开始了:

解压以后,我们就得到了一个交叉编译器的文件夹:

进入这个文件夹,我们就可以看到以下文件夹了:

这里我们主要用到的是交叉编译器文件夹下的bin文件夹,如下图所示:

进入“bin”文件夹中就可以看到非常多的可执行文件了:

这里看着非常多,其实我们就只会用到几个可执行文件。下面为大家依次介绍一下。

aarch64-linux-gnu-gcc :主要用于交叉编译C语言

aarch64-linux-gnu-g++:主要用于交叉编译C++

gdbserver:主要用于在ARM侧启动交叉调试服务

aarch64-linux-gnu-gdb :主要用于连接“gdbserver”进行交叉调试

其实我们主要用到的可执行文件就上面几个,两个用于编译,两个用于调试。这里我们需要注意的是“gdbserver”是放在ARM一侧运行的,所以,我们可以看到它的架构是ARM的:

当然,我们现在也用不到这个,所以放在后面再说。

现在,我们得到了这些可执行文件还不算将交叉编译器安装好了,我们还需要将这个可执行文件目录添加到环境变量中,这一步很重要,这也是为了后面我们编译和调试方便。我们直接在bin目录下输入下面的命令来查看一下当前目录的绝对路径:

pwd

这里需要大家记住这里打印出来的路径,下面修改配置文件会用。

这里我们使用下面的命令打开用户环境变量的配置文件:

nano ~/.bashrc

如果你在这里被提示nano找不到,可以使用下面的命令来安装:

sudo apt isntall nano

我们打开用户环境变量的配置文件以后如图所示:

这里我们来到用户环境变量的最下方,添加下面的一行:

export PATH=/home/chulingxiao/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin:$PATH

这里大家需要注意,我们PATH后面跟的是我们一开始使用pwd命令查询到绝对路径。不要写错了,如果写错了环境变量是没办法正常加载的。

修改完以后,如图所示:

修改完成以后,我们保存退出即可,然后使用下面的命令重新加载环境变量:

source ~/.bashrc

在我们确保环境变量没有问题并且正确加载以后,就可以在终端中输入下面的命令来查看一下我们的环境变量是否添加成功:

aarch64-linux-gnu-gcc --version

这行命令会输出交叉编译器的版本信息:

如果你这里被提示命令找不到之类的,首先检查环境变量的路径有没有设置对,再检配置文件有没有被正确加载。

当然这里如果打印出了交叉编译器的版本号说明环境变量添加正确并且被正确加载。

到这里我们的编译环境就配置完成了。

这里我们只配置编译环境还不行,我们还需要配置调试环境,毕竟本篇文章就是讲交叉调试的。这里我们在终端中输入下面的命令,看看能不能启动gdb:

aarch64-linux-gnu-gdb

这里可以看到,我们这里是启动不起来的,因为我们缺少了一个名为“libncurses”的库:

既然缺这个库我们就需要自己手动安装,这里大家注意在则会个库的“.so”的后面跟了一个数字,这就是依赖这个库的版本,总的来说我们缺少了一个名为“libncurses5”的库,这里我们直接使用下面的命令安装:

sudo apt install libncurses5

安装完成以后,我们再次启动gdb,发现又缺少了一个名为“libpython2.7”的库:

因为这里库名中就跟了一个大致的版本号,所以就不用加后面的版本号了,直接使用下面的命令安装即可:

sudo apt install libpython2.7

安装完成以后,我们再次启动gdb,这里可以看到我们的gdb已经正常启动了:

在gdb的对话框中,我们输入“q”并且回车就可以退出了:

前面为大家演示那些报错就是为了为大家展示,如果在启动gdb报错时应该如何解决,结合上面的思路,我们缺少什么库就安装什么库。最终都可以解决依赖关系。

至此,我们交叉编译环境就已经安装完成了。

四、开发板一侧gdbserver配置

        之前也为大家说过,我们交叉调试本质其实是依赖网络进行的,这里我们需要在开发板一侧启动gdbserver我们的X86主机才能对其进行交叉调试,所以现在我们就需要将gdbserver这个可执行程序上传到开发板中,之前我们也看了,在交叉编译器中的这个gdbserver的架构是arm64的,所以它可以直接运行在开发板上。这里需要注意的是,我们使用的交叉编译器和gdbserver必须来自一个交叉编译器的压缩包中,不然可能会出现很奇怪的情况。

这里我使用的是sftp将X86主机的gdbserver上传到开发板中,如果你对Linux比较熟悉,sftp你因该比较熟悉,这里就不细说了。当然你也可以不使用sftp总之能将文件上传到指定目录就行:

这里可以看到我将gdbserver这个可执行文件上传到了开发板的“/usr/bin”目录下,因为这个目录本来就在环境变量中,我们的可执行文件可以直接被找到。当文件传输完成以后,我们直接在开发板的终端中输入下面的命令,注意这里是在开发板的终端中:

gdbserver --version

如果可以正常打印版本信息的话,说明在开发板一侧,gdbserver已经准备好了:

至此,我们开发板一侧的环境就配置完成了。

五、交叉编译程序与gdb测试

        当我们搭建好前面的环境以后,我们就可以编译一段代码来测试一下了,首先我们新建一个文件夹,这里我就新建一个名为test的文件夹,直接使用下面的命令:

mkdir test

进入这个文件夹以后,我们使用下面的命令来新建一个.c的文件:

touch main.c

这里我们使用下面的命令打开这个文件:

nano main.c

我们将下面的测试代码复制到这个.c文件中:

#include "stdio.h"
int main()
{printf("Hello World\n");printf("Hello GCC\n");printf("Hello GDB\n");return 0;
}

这里的代码很简单,是C语言中最基础的“Hello World”程序,我们后面就使用这个基础的测试程序来测试gdb调试。

这里我们保存并退出文件,这里我们使用下面的命令来将这个.c的文件编译成可执行文件:

aarch64-linux-gnu-gcc -o main main.c -g -O0

下面我来解释一下这段命令,首先就是“aarch64-linux-gnu-gcc”,这就是我们使用的交叉编译器,然后是“-o main”表示输出的可执行文件的名字,这里我们可执行文件名为“main”;然后是“main.c”,这是我们要编译的c文件。“-g”表示将这个文件编译为Debug版本,这也是为了方便我们后面的调试,“-O0”表示我们编译时的优化等级,注意这里的“-”后面是一个“O”再后面是0,这里的0就是编译优化等级,0表示不优化。

编译以后,我们就得到了一个名为“main”的可执行文件:

这个被我们编译出来的可执行文件在我们的计算机上肯定是不能运行的:

因为这个一个arm64架构的可执行文件,我们只能将其放到arm设备中运行。

这里我们同样将这个可执行文件通过sftp传输到开发板端:

这里我们在开发板端执行这个可执行文件测试一下,我们可以看到,这个可执行文件可以正常打印:

下面我们可以调试测试一下,这里我们首先在开发板启动调试服务器,这里我们使用下面的命令:

gdbserver :8000 ./main

这里的“:8000”表示对外开放的调试端口。后面的“./main”是我们要调试的可执行文件,启动gdbserver以后,我们回到计算机一侧,我们使用下面的命令先启动一下gdb:

aarch64-linux-gnu-gdb ./main

这里的“./main”是我们要调试的程序,输入命令以后就启动了gdb的对话框:

这里我们在gdb的对话框中,使用下面的命令连接开发板:

target remote 192.168.112.50:8000

这里的IP地址就是我们的开发板的IP地址,这里需要我们开发板的IP地址和我们查询到的主机的IP地址在一个网段内,这里很重要。

输入命令以后,我们就可以看到调试已经连接上了:

这里我们在gdb对话框中输入下面的命令进入主函数:

break main  

这里我们可以看到来到的地址和这段代码在文件中的行数:

本质上我们使用“break main”是在主函数处打了一个断点,程序是停在了这里我们这里使用下下面的命令来到让程序继续运行:

continue 

运行上面的命令以后,我们就能看到我们程序继续运行,并且显示调试到了程序中了哪一行:

这里我们在gdb对话框中使用下面的命令调试到下一行:

next 

往下调试完一步以后,我们就可以发现,在开发板一侧的终端中打印出了一行内容:

打印出的这一行就是我们调试过去的一行:

这里我们将所以行都调试过去:

开发板端已经打印出了所有内容:

这里我们的调试就已经完成了。这里至少也证明了我们的gdb调试功能没有问题。

当然,大家肯定已经发现了,这样交叉调试真的是太反人类了,没有图形化不说还都是用命令操作。有没有更好的解决方案呢?当然有,那就是借助vs code进行调试,这个我们放到后面再讲。

六、使用vs code交叉调试Linux程序

        在前面相信大家已经看到了,我们使用命令行的gdb交叉调试时,太困难了,所以我们这里就需要借助vs code的强大插件生态来实现图形化的交叉调试。

这里我们首先需要下载一个vscode,这里我们直接使用ubuntu内部的浏览器来下载vscode的安装包,这里我们启动浏览器,直接搜索vscode:

 一般我们搜出来的第一个就是vscode的官网:

进入官网以后,直接西在deb文件就好了:

下载完成以后,我们得到了一个.deb的软件包:

这里我们直接使用下面的目录安装vscode:

sudo dpkg -i code_1.98.2-1741788907_amd64.deb

在弹出的弹窗中,我们直接回车即可:

随后我们的vscode就安装完成了:

随后vscode就出现在我们的软件列表中了:

vscode启动以后,就能看到以下界面了:

这里我们先安装一个中文的插件:

这里中文插件的安装大家应该都比较熟悉了,这里就不细说了。

重启以后,我们的vscode就变成中文了:

这里我们再安装一个C语言相关的插件,其中的调试功能也集成在其中了,我们直接搜索“C/C++”:

这里我们需要安装这个名为“C/C++ Runner”的插件。安装完成以后,如图所示:

至此,我们所需的交叉调试插件就安装好了,是的,关于调试的插件其实就只有一个。

这里我们选择“打开文件夹”:

这里我们直接选择我们之前创建的文件夹即可,这个文件夹中包含了我们的可执行文件和源文件:

我们就在这个界面按下“F5”,不出意外的话,会出现这个错误:

这是因为我们没有修改相关的配置文件,这里我们再次回到项目目录中,可以看到,当我们按下“F5”以后,应该会在我们的项目目录下生成一个名为“.vscode”的文件夹:

这个文件夹下生成了几个配置文件,我们这里只需要关注“launch.json”文件,这就是我们的调试配置文件:

打开这个文件,我们可以看到以下内容:

如果你没有正常生成“.vscode”这个目录,可以自己新建目录和“launch.json”文件。

我i们将“launch.json”文件原本的内容删除,将下面的内容写入文件:

{"version": "0.2.0","configurations": [{"name": "gdb server",//配置名称;在启动配置下拉菜单中显示"type": "cppdbg",//配置类型。"request": "launch",//请求配置类型。可以是“启动”或“附加”。"program": "${workspaceFolder}/main",//需要调试的可执行文件"args": [],//传递给程序的命令行参数。"stopAtEntry": true,//可选参数。如果为true,则调试器应在目标的入口点停止。如果传递了进程ID,则无效。"cwd": "${workspaceFolder}",//目标的工作目录"environment": [],//要添加到程序环境中的环境变量。示例:[“name”:“squid”,“value”:“clam”]。"externalConsole": false,//如果为true,则为调试对象启动控制台。如果为false,则在Linux和Windows上,它将出现在集成控制台中。"linux": {"MIMode": "gdb",//指示midebugengine将连接到的控制台调试器。允许值为“gdb”“lldb”。"miDebuggerPath": "aarch64-linux-gnu-gdb",//调试器的路径。},"miDebuggerServerAddress": "192.168.112.50:8000",//要连接到的调试器服务器的网络地址(例如:localhost:1234)。"setupCommands": [//要执行的一个或多个gdb/lldb命令,以便设置底层调试器。{"description": "Enable pretty-printing for gdb",//命令的可选说明。"text": "-enable-pretty-printing",//要执行的调试器命令。"ignoreFailures": true,//如果为true,则应忽略来自命令的失败。默认值为假。                }]}]
}

这里看起来非常复杂,这里我们只需要改几行就行了,下面依次为大家讲解。

首先就是"program": "${workspaceFolder}/main"这一行,这里我们需要填写我们要填写可执行文件的路径,首先大家需要理解workspaceFolder的概念,当我们使用vscode打开一个文件夹以后,workspaceFolder变量就变成了这个文件夹路径,假如我项目文件夹的路径为“/home/chulingxiao/test”这里workspaceFolder路径就是这个。这里我们可执行文件路径就在项目的目录下,并且名为main,所以这里完整路径为“/home/chulingxiao/test/main”。不管怎样,这里大家只要把可执行文件路径写在这里就行。

然后是"miDebuggerPath": "aarch64-linux-gnu-gdb"这里需要我们填写自己的gdb调试器,因为我们已经前面已经将gdb调试器所在的目录添加到环境变量了,所以这里这里直接写gdb调试器的名字即可。如果前面大家没有添加,可以直接写绝对路径。

然后就是 "miDebuggerServerAddress": "192.168.112.50:8000",这里的IP地址大家直接填写要交叉调试的设备的IP地址,端口号就是我们在开发板一侧启动gdbserver时指定的端口。

这里我们只需要修改这几个地方,大家需要根据自己的情况自行修改。

修改好调试的配置文件后,大家记得保存,然后我们在开发板一侧启动gdbserver:

随后我们在vscode中进入调试界面:

 这里我们需要选择“gdbserver”:

然后我们再回到vscode中再按“F5”,就可以看到调试已经启动了:

这里的调试就和我们在普通IDE中的调试非常像了,这里我们按如图所示按键可以去到下一条代码:

点击如图所示的按键可以进入函数:

这里在代码前面也可以打断点。

这就是大概的使用教程,具体的还是让大家自己摸索吧,至少现在我们可以使用图形化进行交叉调试了。

至此,我们使用vscode交叉Linux程序就已经完成了。

七、结语

        本次教程教了大家如何使用vscode交叉ARM Linux程序,相信大家看了本次教程以后,对C语言的编译与调试一定有更深刻认识了。那么最后,感谢大家观看!

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

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

相关文章

视频号私信自动化回复插件

给自己的浏览器插件又增加了视频号斯信的自动化回复搜索:程序员老狼主体逻辑就是,不停的点击打招呼和斯信那个tab切换查看有无小红点,有小红点的会话,就点击。查看有无打招呼,有打招呼就点击,抓取昵称和内容…

Web前端实现银河粒子流动特效的3种技术方案对比与实践

文章目录 前端实现银河粒子流动特效的技术原理与实践 引言:银河粒子特效的技术背景与现状 技术发展历史 当前技术现状 技术原理与实现方案 思维导图:银河粒子特效技术架构 1. CSS3实现方案 基础实现代码 性能优化技巧 2. Canvas 2D实现方案 基础实现代码 Canvas高级优化技术 …

Linux:告别Jammy,拥抱Noble!WSL Ubuntu 22.04 到 24.04 LTS 终极升级指南

大家好!如果大家和我一样,是Windows Subsystem for Linux (WSL) 的忠实用户,那么大家一定对Ubuntu在其中的表现印象深刻。我们中的许多人可能还在使用稳定可靠的Ubuntu 22.04 LTS (Jammy Jellyfish)。但现在,一个更令人兴奋的时代…

江协科技STM32 11-1 SPI通信协议

本节课我们将继续学习下一个通信协议,SPI。SPI通信和我们刚刚学习过的I2C通信差不多。两个协议的设计目的都一样都是实现主控芯片和各种外挂芯片之间的数据交流,有了数据交流的能力,我们的主控芯片就可以挂载并操纵各式各样的外部芯片&#x…

预过滤环境光贴图制作教程:第一步 - HDR 转立方体贴图

在基于物理的渲染(PBR)中,环境光贴图是实现真实光照效果的核心组件之一。而将 HDR 全景图转换为立方体贴图,是制作预过滤环境光贴图的基础步骤。本教程将详细讲解如何实现这一转换过程。 什么是 HDR 转立方体贴图? HDR(高动态范围)全景图通常以等矩形投影(Equirectan…

02 深度学习介绍【动手学深度学习v2】| 学习笔记

1、intro自然语言处理虽然我们过去取得了很大的进展,但是实际上还是停留在感知层面。计算机视觉领域,因为图片里面都是像素,像素很难用符号学来解释,所以计算机视觉大部分是用概率模型或机器学习来做。深度学习它是机器学习的一种…

智能学号抽取系统V5.6.4重磅发布

告别随机数,拥抱智能点名!—— 全新升级的“智能学号抽取系统V5.6.4”重磅发布! 摘要: 还在为课堂随机提问、活动抽奖而手动翻名单、查表格而烦恼吗?还在忍受传统点名工具的简陋和不智能吗?今天&#xff0…

Leetcode-141.环形链表

dict和set 1. 结构上的区别:类型键(Key)值(Value)示例dict有有{a: 1, b: 2}set有没有{a, b} dict 是**键值对(key-value)**的集合。set 是只有键(key)没有值的一组唯一元…

调节步进电机速度时调PSC和调ARR的区别

在步进电机控制中,调节速度通常是通过改变脉冲频率实现的。代码中选择调节ARR(Auto-Reload Register)而非PSC(Prescaler)的原因如下: 1. ARR 与 PSC 的核心区别 • ARR(自动重载寄存器&#xff…

在 AKS 中运行 Azure DevOps 私有代理-1

简介 配置 Azure DevOps 私有代理的传统方法是将其部署在虚拟机 (VM) 上。然而,一个有趣的替代方案是利用 Azure Kubernetes 服务 (AKS) 来实现此目的。 本文将指导您如何使用 Helm Chart 在 AKS 集群中设置 Azure DevOps 私有代理,并提供该过程的分步说明。 在 AKS 中部署…

C# _Json数据

目录 1、添加Json库 2、数据序列化(对象转 JSON)和反序列化(JSON 转对象)操作 3、序列化 创建和读取Json数据 创建Json数据 定义一个CreateJson方法 读取 解析 Json数据 定义一个ReadJson方法 4、程序运行结果 在 C# 中&…

JavaScript 原始值与引用值

JavaScript 原始值与引用值 ECMAScript变量可以包含两种不同类型的数据:原始值和引用值。 原始值(primitive value)就是最简单的数据,引用值(reference value)则是由多个值构成的对象。 保存原始值的变量是…

linux中挂载磁盘和卸载

查找磁盘 找到你想要挂载的磁盘。可以使用lsblk或fdisk -l命令来查看系统中所有的磁盘和分区信息。 lsblk 对数据盘进行分区 在fdisk交互界面里,按以下步骤操作 fdisk /dev/vdb- 输入n来创建新分区。 - 按照提示设置分区的起始扇区、结束扇区等信息,…

java8学习笔记-Stream流

JDK1.8新增了Stream类,从而把函数式编程的风格引入到Java语言中,Stream类的API提供了强大的功能,使用Stream后,可以写出更加强大,更加简洁的代码首先,Stream流有一些特性:Stream流不是一种数据结…

Flutter开发 dart语言基本语法

特点 Dart语言支持JIT与AOT。 Dart语言采用单线程模型。 Dart语言是强类型编程语言,但是允许弱类型语言式编程。 基本语法 1.变量和常量 变量 var、object、dynamic关键字或数据类型显式声明变量。 命名规则: 变量名称必须由数字、字母、下划线或$组成&a…

SpringBoot:基于 Redis 自定义注解实现后端接口防重复提交校验(幂等操作)

SpringBoot:基于 Redis 自定义注解实现后端接口防重复提交校验(幂等操作)可基于 时间间隔 和 用于幂等判断的参数名称 实现防重复提交校验 客户端发送请求 ↓ [Spring Boot 应用入口]↓ ┌─────────────────────────…

【语音技术】意图与语料

目录 1. 意图 1.1. 意图分类 1.1.1 入口意图(Entry Intent) 1.1.2 对话意图(Dialog Intent) 1.2. 意图类型切换操作步骤 2. 语料 2.1 语料分类详解 2.2 语料编写规范详解 2.3 标签符号深度说明 3. 词槽 3.1 符类型要求 …

【MySQL集群架构与实践5】使用Docker实现水平分片

目录 一. 在Docker中安装ShardingSphere 二. 实践:水平分片 2.1 应用场景 2.2 架构图 2.3 服务器规划 2.4 创建server-user容器 2.5 创建server-order0和server-order1容器 2.6.日志配置 2.7 数据节点配置 2.8.测试数据节点 2.8.1.测试server_order0.t_or…

视觉图像处理中级篇 [1]—— 彩色照相机的效果与预处理

在工业检测中,黑白相机虽应用广泛,但在应对颜色差异检测时往往力不从心。彩色照相机凭借其对色彩信息的精准捕捉,成为复杂场景下的理想选择,而预处理技术则进一步释放了其性能潜力。一、彩色照相机的效果检查盖子上的金色标签可以…

使用 BERT 的 NSP 实现语义感知切片 —— 提升 RAG 系统的检索质量

在构建 Retrieval-Augmented Generation(RAG)系统时,文档的切片方式至关重要。我们需要将长文本切分成合适的段落(chunks),然后存入向量数据库进行召回。如果切得太粗,会丢失上下文细节&#xf…