【Linux】解锁软硬链接奥秘,高效动静态库管理的实战技巧
软硬连接和动静态库
- 1. 软链接
- 1.1. 概念
- 1.2. 特点
- 1.3. 应用场景
- 2. 硬链接
- 2.1. 概念
- 2.2. 硬链计数
- 2.3. 特点
- 2.4. 应用场景
- 3. 动静态库
- 3.1 库存在的原因
- 3.2. 静态库制作与使用
- 3.2.1 打包
- 3.2.2. 使用
- 3.3. 动态库制作与使用
- 3.3.1. 打包
- 3.3.2. 使用
- 4. 解决'动态库查不到'的4种方法
- 4.1. 库安装
- 4.2. 软链接
- 4.3. /etc/ld.so.conf.d配置文件
- 4.4. LD_LIBRARY_PATH环境变量
- 5. 动静态链接的选择
- 6. 理解动态库加载
- 6.1. 站在OS角度理解
- 6.2. 编址
- 6.3. 理解动态链接和加载问题
- 6.3.1. 一般程序的加载
- 6.3.2. 动态库的加载
1. 软链接
1.1. 概念
- 软链接概念:也称为符号链接,是一种特殊类型的独立文件,它不直接包含文件的实际内容,而是包含了指向目标文件或目录的路径,类似于Windows中的快捷方式。当访问链接时,系统会根据链接中存储的路径找到并访问目标文件或目录。
ln -s 目标路径 链接路径
1.2. 特点
-
存储内容:软链接文件不直接包含文件的实际内容,而是包含了指向目标文件或目录的路径字符串。
-
独立文件:软链接文件在文件系统中是一个独立文件,拥有自己的inode编号和属性。
-
访问方式:通过软链接访问文件或目录时,系统首先读取软链接文件中的内容(即:路径信息),然后根据该路径找到并访问实际的目标文件或目录。
-
跨文件系统:软链接可以跨文件系统使用,即:可以链接到不同文件系统中的文件或目录。
-
删除与移动:如果目标文件被删除或移动,软链接将变为无效(即:死链接),但删除软链接本身,不会影响目标文件或目录。
1.3. 应用场景
-
快速访问文件:当某个文件位于深层次的目录中,通过创建一个指向该文件的软链接,就可以快速访问到该文件,简化了文件访问过程。这类似于Windows中的快捷方式。
-
动态库版本管理:对于共享库,可以使用软链接来管理不同版本动态库之间的切换。如:创建一个指向最新版本动态库的软链接,当库升级时,仅需要更新软链接指向新版本的动态库。
2. 硬链接
2.1. 概念
- 硬链接概念:指多个文件名指向同一个物理文件的链接关系。这些链接在文件系统中具有相同的inode编号,但可以位于不同的目录中。
建立硬链接,并没有新建文件,而是为文件创建了新的文件名,硬链接不是一个独立的文件,因为inode与目标文件的inode相同。
- 硬链接本质是在指定目录下,插入新的文件名和inode之间的映射关系,并让inode中的硬链接计数++。
ln 源路径 硬链接路径
2.2. 硬链计数
一、硬链接计数的概念
- 概念:在linux中,每个inodo中都有一个硬链接计数,它表示有多少个文件名指向这个inode。
二、硬链接计数的变化场景
-
创建文件:当创建一个新文件时,这个文件的硬件计数默认为1,因为此时只要一个文件名指向这个inode。
-
创建硬链接:当使用ln创建一个文件的硬链接,不会创建一个新的文件,只会为该文件创建一个新的文件名,并增加inode中的硬链接计数。
-
删除文件:当删除一个文件时,会删除指向该文件的文件名,并减少inode中的硬链接计数,如果此时硬链接计数等于0,文件才会被删除,系统回收该inode及其所占的磁盘空间。
三、硬链接计数的限制
-
不能跨文件系统:硬链接只能在同一文件系统内创建,不能跨文件系统或分区,因为inode只在分区内唯一。
-
不支持目录:在linux中,默认情况下,不能对目录创建硬链接,否则会导致环路问题。
问:为什么目录链接计数默认不为1?
- Linux中,每个目录都包含两个特殊的目录 “.“和”. .”,".“代表当前目录,”. ."代表上级目录,它们在目录被创建时就自动生成,并作为硬链接存在。
💡Tips:一个目录下,子目录数 = 主目录硬链接计数 - 2。
2.3. 特点
-
共享inode:硬链接与原始文件共享同一个inode编号,意味着它们指向同一个物理文件的数据块,对物理文件所做的任何更改都将反映在所有硬链接上。
-
增加访问路径:创建硬链接实际上是为文件增加了一个新的访问路径或文件名。
-
无差别访问:无论通过哪个文件名访问文件,都指向同一个inode,即:指向同一个文件内容。因此硬链接与原始文件无差别,二者等价。
-
节省空间:由于硬链接共享相同的inode和数据块,因此它们不会占用额外都磁盘空间。
-
删除与移动:如果删除目标文件或硬链接,只要inode中的硬链接计数不为0,文件仍可以被硬链接访问,直到硬链接计数=0,文件才被真正删除。
-
只能在同一文件系统(分区)内创建,不允许对目录创建硬链接。
2.4. 应用场景
硬链接应用场景如下:数据备份、数据共享、数据恢复、版本控制、自动同步等。
3. 动静态库
- 库文件:将多个对象文件(.o文件)打包在一起的文件。
如果我希望其他人能够使用我编写的方法,通常的方法是提供一组同名方法.o文件(预编译的对象文件),然后将所有.o文件打包形成一个库文件,和相应的同名方法.h头文件。即:库文件 + 头文件。
3.1 库存在的原因
- 提高开发效率。
库底层封装了重复的代码和常用的功能,使得开发者在编写项目时可以直接使用这些现成的代码,而无需从头开始编写,这大大减少了开发的时间,提高了开发效率。
- 隐藏源代码。
这意味着用户只能看到库提供的接口(通过头文件.h),而无法直接访问或修改库中的源代码,这有助于保护开发者的知识产权和代码实现。
3.2. 静态库制作与使用
#include"my_add.h"int my_add(int a, int b)
{return a + b;
}
#include"my_sub.h"int my_sub(int a, int b)
{return a - b;
}
3.2.1 打包
ar [options] archive-file object-files
-
archive-file是静态库名(lib库名.a);object-files是要添加到库中的对象名(.o文件)。
-
常见的选项
-c:创建库文件,如果库已存在,则会被覆盖。
-r:向库文件中添加.o文件,如果.o文件已在库中存在,则会被替换。
-t:列出库文件中包含的.o文件列表。
-v:在执行过程中显示详细的信息。
第一步:编译形成 .o 文件。
第二步:使用ar命令,将所有.o文件进行打包,形成静态库文件。
第三步:将库进行标准化。
- 库的标准化:通常将头文件或库文件分别放在不同的文件夹中,可以提高项目的可维护性和组织性。
libmyc.a:my_add.o my_sub.o //第二步:使用ar命令,将所有.o文件进行打包,形成静态库文件ar -rc $@ $^%.o:%.c //第一步:编译形成 .o 文件gcc -c $<.PHONY:clean
clean:rm -rf *.a *.o mylib mylib.tgz.PHONY:output //第三步:将库进行标准化
output: mkdir -p mylib/includemkdir -p mylib/lib cp -rf *.h mylib/include/cp -rf *.a mylib/lib/tar czf mylib.tgz mylib
3.2.2. 使用
#include"my_add.h"
#include"my_sub.h"int main()
{int a = 4, b = 3;printf("%d + %d = %d\n", a, b, my_add(a, b));printf("%d - %d = %d\n", a, b , my_sub(a, b));return 0;
}
- -I(i的大写):用来指定编译器搜索头文件的额外路径。
当编译器在编译过程中遇到#include指令时,它先会在标准的位置(当前目录或系统默认的头文件路径)来查找指定的头文件,如果查找不到,编译器就会使用-I指定的路径进行搜索。
- -L:用来指定链接器搜索库文件的额外路径。
当链接器在链接中需要找到某个库文件(.so、.a),它先会在标准的位置(系统默认的库路径)中查找,如果查找不到,链接器就会使用-L指定的路径进行搜索。
- -l(L的小写):用来指定链接器在链接过程中要链接的库。
补充:头文件的搜索路径:当前目录、系统默认的头文件路径(/usr/include、/usr/local/include)、gcc内置的标准头文件路径、命令行中通过-l选项指定的头文件路径。 库文件的搜索路径:系统默认的库文件路径(/usr/lib、/usr/local/lib)、gcc内置的库文件路径、命令行中通过-L选项指定的库文件路径、环境变量LIBARY_PATH中指定的路径。
这些选项分别用于控制编译和链接过程中的头文件、库文件的搜索路径和库文件的选择。
3.3. 动态库制作与使用
3.3.1. 打包
第一步:使用-fPIC选项,编译形成 .o 文件。
- -fPIC:用于指示编译器生成与位置无关的代码,无论代码被加载到内存的哪个位置,它都能正确运行,而不依赖于它在编译或加载时的具体地址。这种特性通过使用相对寻址,而不是绝对寻址来实现的。这对于创建共享库是至关重要的,因为共享库可以在进程地址空间的任何位置被加载。
第二步:使用-shared,将所有.o文件进行打包,形成动态库文件。
- -shared:告诉编译器gcc生成一个共享库(.so或.dll文件)。
第三步:将库进行标准化。
libmyc.so:my_add.o my_sub.o //第二步:使用-shared,将所有.o文件进行打包,形成动态库文件gcc -shared -o $@ $^%.o:%.c //第一步:使用-fPIC选项,编译形成 .o 文件gcc -c -fPIC $<.PHONY:clean
clean:rm -rf *.so *.o mylib mylib.tgz.PHONY:output //第三步:将库进行标准化
output: mkdir -p mylib/includemkdir -p mylib/lib cp -rf *.h mylib/include/cp -rf *.so mylib/lib/tar czf mylib.tgz mylib
3.3.2. 使用
现象:程序运行时,OS加载动态库文件myc失败,即:系统找不到这个文件。
分析如下:a. 静态库在编译阶段会被链入到可执行程序中,即:库的代码和数据会被直接拷贝到最终可执行程序中;程序在运行时不在需要静态库文件。 b.动态库在编译时只需要找到头文件,包含了对库中函数和数据的引用(通常是符号名和地址偏移量);程序在运行时,OS需要找到动态库文件,以便将库中的代码和数据加载到内存中。如果OS找不到动态库文件,程序无法加载,从而导致运行时错误。
4. 解决’动态库查不到’的4种方法
4.1. 库安装
-
将库或其他软件安装到系统中,本质是把对应的文件,拷贝到系统默认的搜索路径中。
-
在64位系统,系统中库默认的搜索路径为/lib64、/usr/lib64;在32系统,系统中库默认的搜索路径为/lib、/usr/lib。
4.2. 软链接
4.3. /etc/ld.so.conf.d配置文件
- /etc/ld.so.conf.d目录下的配置文件,用来指定额外的库文件的搜索路径,以便动态链接器能够在运行时找到并加载这些库文件。
4.4. LD_LIBRARY_PATH环境变量
- LD_LIBRARY_PATH:是一个环境变量,在linux中,为动态链接器指定额外的库搜索路径。
5. 动静态链接的选择
- 动静库同时存在:gcc默认会使用动态库进行动态链接;若想要进行静态链接,必须加上-static选项。
- 只存在静态库:可执行程序只能进行静态链接,程序不一定整体是静态链接的。
可执行程序只能进行静态链接,指的是对于特定库的链接方式: 当系统中只存在某个库的静态版本,任何尝试链接到这个库的程序都必须使用使用静态链接,因为动态链接器在运行时无法找到这个库的动态版本。
程序不一定整体是静态链接的,取决于它所依赖的所有库,以及编译链接时的选项: 一个程序可能依赖于多个库,此外,即使程序使用了静态链接来链接某些库时,它仍可能依赖于动态链接的库(C、C++标准库或系统库),这些库在OS级别上提供,且以动态链接的形式存在,以便在多个程序之间共享。
- 只存在动态库:只能进行动态链接,若非得进行静态链接,编译器或链接器会报错。
6. 理解动态库加载
6.1. 站在OS角度理解
一、动态库概念
- 动态库:也称为共享库,是一种包含代码和数据,可以在多个程序之间共享的文件,存放在磁盘上。
与静态库不同,静态库在程序编译时会被完全复制到可执行文件中,而共享库则在程序运行时被加载到内存中,如果多个程序使用同一个共享库,OS会让这些进程共享内存中的同一份库代码和数据,即:动态库的代码和数据在内存中只存在一份。
- 管理:系统中可以同时存在多个已经被加载的库,OS需要管理它们,先描述(包含了加载地址等信息)、再组织。
二、动态库加载的过程
-
检查依赖:程序启动时,动态链接器会检查该程序依赖的所有动态库。
-
搜索路径:动态链接器会在预设的库搜索路径中查找所需的动态库文件。
-
加载与映射:第一次加载、后续加载。
第一次加载:如果动态库尚未被加载到内存中,动态链接器会将该库加载到内存中,并映射到进程地址空间的共享区中。
后续加载:如果其他进程也需要共享这个库,动态链接器会检查内存中是否已存在该库;如果已存在,只需修改地址空间中共享区的映射关系,指向已存在的库副本;如果不存在,则重复第一次加载的过程。
- 优点:节省内存、易于更新、提高了程序的性能和安全性。
6.2. 编址
-
可执行程序在编译和链接完成后就已经具有了明确的格式信息,且在文件中按照类别划分了不同的区域 (如:代码段、未初始化数据段(BBS段)、初始化数据段),每个区域都有其对应的地址信息,通常是相对地址(虚拟地址)。
-
编址:在编译和链接阶段,为程序和库中的符号(变量、函数)分配地址的过程,主要有绝对编址、相对编址两种方式。
可编址的范围:32位平台,[0, 2^32] -> [0, 4GB] ,64位平台,[0, 2^64] -> [0, 16GB]。
- 绝对编址:在编译和链接过程中,符号的地址是固定的,即:已经确定了符号的实际的物理内存地址。这种方式要求程序运行时,必须加载到特定的物理地址处,否则无法正确的运行。
绝对编址中的地址 == 实际的物理内存地址。
在计算机早期,程序使用绝对编址,因为当时系统比较简单,程序通常使用直接映射到物理内存的绝对编址,而没有复杂的内存管理和保护机制,如:虚拟内存、页表等。
- 相对编制:也成为逻辑地址、虚拟地址。在编译和链接过程中,符号的地址是不固定的,而是相对于某个基地址的偏移量。这种方式允许程序在加载时动态确定实际地址,从而实现位置无关代码。
符号地址 = 基地址 + 偏移量。基地址在编译链接阶段是未知的,通常是由OS在程序加载时分配的虚拟地址,是在地址空间内的一个起始地址,如:0x400000。
现代计算机系统广泛使用相对编址,因为这提供了更好的灵活性和安全性。
问:地址空间、页表中的数据来自哪里?
- 当基地址确定后,OS会使用可执行程序中各个区域的虚拟地址,来初始化进程地址空间、页表。每个区域在进程地址空间都有一个相对应的虚拟地址范围。在程序被加载到内存中,OS会自动分配物理内存,并构建页表来建立虚拟地址和物理地址之间的关系。
每个可执行程序大小不同,说明了每个程序中各个区域虚拟地址范围也会不同。相应地,当这些程序被加载到内存变为进程时,则每个进程地址空间中各个区域的虚拟地址的范围也是不同的。
6.3. 理解动态链接和加载问题
6.3.1. 一般程序的加载
一、一般程序加载的过程
-
读取可执行文件,并解析文件中各个段的信息:OS先从存储介质(如硬盘)中读取可执行文件(程序代码、数据以及依赖的库),然后OS会解析可执行文件中的各个段(如代码段、数据段、堆栈段等)的信息。这些段包含了程序运行所需的所有指令和数据。
-
分配虚拟地址空间、并确定基地址。
-
加载程序段、初始化地址空间:OS将可执行文件中的各个段加载到地址空间的相应位置。
4.重定位:在加载过程中,OS会进行重定位操作。这包括解析程序中的符号引用(如函数名、变量名等),并将它们转换为实际的物理内存地址。
-
初始化数据段和未初始化数据段、构建页表。
-
设置程序计数器(PC指针):在程序开始执行之前,OS会将PC指针设置为程序入口点的地址(main函数的地址),这是程序执行的第一条指令的虚拟地址。
-
执行程序:CPU会根据程序计数器中的地址从内存中读取指令,并执行它。
二、地址空间的构建和管理,需要由CPU、编译器、OS三者共同配合完成。
-
CPU提供硬件支持,cr3寄存器存储页表的指针,MMU负责将虚拟地址转化为物理地址。
-
编译器负责将源代码编译成机器码,并生成可执行文件,这个文件包含了各个段的信息; 编译器在编译过程将程序中的符号地址编译成相对于基地址的偏移量;
-
OS负责创建地址空间,并选择一个基地址; OS负责加载程序的各个段来初始化地址空间,并进行重定位来确定实际物理内存; OS负责创建和初始化页表,将虚拟地址转化为物理地址; OS处理缺页中断,动态分配物理内存。
三、CPU执行程序的过程
OS读取可执行程序表头中的入口地址(main),把它交到CPU,CPU的程序计数器指向main函数的虚拟地址0x401020,CPU从这个地址开始执行指令:取指令(虚拟地址) -> 地址转换 -> 分析指令 -> 执行指令 -> 更新PC指针(虚拟地址)。
CPU从当前PC指向的虚拟地址处读取指令,即:取指令 -> CPU中MMU使用页表将虚拟地址0x401020转化为物理地址0x112233,即:地址转换 -> CPU从物理地址0x112233处读取指令,并解码指令,即:分析指令 -> CPU根据解码的指令执行相应的操作,即:执行指令 -> 更新程序计数器,使其指向下一个指令的地址。
6.3.2. 动态库的加载
对于库的数据和方法的访问,都是可以通过库在地址空间的起始地址+程序内部的偏移量来实现。
相关文章:

【Linux】解锁软硬链接奥秘,高效动静态库管理的实战技巧
软硬连接和动静态库 1. 软链接1.1. 概念1.2. 特点1.3. 应用场景 2. 硬链接2.1. 概念2.2. 硬链计数2.3. 特点2.4. 应用场景 3. 动静态库3.1 库存在的原因3.2. 静态库制作与使用3.2.1 打包3.2.2. 使用 3.3. 动态库制作与使用3.3.1. 打包3.3.2. 使用 4. 解决动态库查不到的4种方法…...

【设计模式】Python 后端开发中的工厂模式设计与实现
Python 后端开发中的工厂模式设计与实现 1. 引言 在后端开发中,如何设计一套易于扩展、可维护且灵活的系统架构是开发者面临的重要课题。设计模式在这一过程中扮演了至关重要的角色,尤其是在面向对象编程中,它提供了大量解决重复问题的标准…...

划重点!入门安全测试,这几点要注意!
朋友们,今天我们一起来学习下如何做安全测试。 那么首先,什么是安全测试? 安全测试是评估和验证软件系统、应用程序或网络的安全性和强度的过程。其目标是发现和修复潜在的安全漏洞和脆弱性,以确保系统能够抵御恶意攻击和未授权…...

mysql 09 独立表空间结构
表空间中的页实在是太多了,为了更好的管理这些页面,设计 InnoDB 的大叔们提出了 区 (英文名: extent )的概念。对于16KB的页来说,连续的64个页就是一个 区 ,也就是说一个区默认占用1MB空间大小。…...

linux 虚拟环境下源码安装DeepSpeed
第一步:创建虚拟环境: conda create -n deepspeed python3.10 第二步:进入虚拟环境,安装Pytorch 2.3.1 # CUDA 12.1 conda install pytorch2.3.1 torchvision0.18.1 torchaudio2.3.1 pytorch-cuda12.1 -c pytorch -c nvidia 第…...

常见八大排序算法
今天我们带来数据结构中常见的8大排序算法。 排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性冒泡排序O(n方)O(n方)O(n方)O(1)稳定插入排序O(n方)O(n方)O(n方)O(1)稳定选择排序O(n方)O(n方)O(n方)O(1)不稳定希尔排序O(n1.3方到1,5方)O(n)O(n方)O(1)不稳定堆排序O(n lo…...

汽车免拆诊断案例 | 2022款大众捷达VS5车行驶中挡位偶尔会锁在D3挡
故障现象 一辆2022款大众捷达VS5汽车,搭载EA211发动机和手自一体变速器,累计行驶里程约为4.5万km。该车行驶中挡位偶尔会锁在D3挡,车速最高约50 km/h,且组合仪表上的发动机故障灯和EPC灯异常点亮。 故障诊断 用故障检测仪检…...

Linux之HugePage的原理与使用
Linux之HugePage的原理与使用 虚拟地址与物理地址虚拟地址物理地址虚拟地址与物理地址的转换 HugePage的概念Linux使用HugePage创建HugePage在程序中使用HugePage 总结 虚拟地址与物理地址 在研究HugePage之前,首先需要明白虚拟地址和物理地址的概念。在计算机系统…...

一步步优化Redis实现分布式锁
分布式锁概念 在多线程的程序里,为了避免同时操作一个共享变量产生数据问题,会加一个互斥锁,以确保共享变量的正确性,使用范围是同一个进程。 那如果是多个进程,需要同时操作一个共享资源,如何互斥呢&…...

C++进阶——二叉搜索树
目录 一、基本概念 二、性能分析 三、模拟实现 四、使用场景 1.key搜索场景 2.key/value搜索场景 一、基本概念 二叉搜索树(Binary Search Tree),看名字就知道,是可以用来搜索数据的一种二叉树。 它可以是空树(一个数据都…...

Require:业界优秀的HTTP管理方案。
方案异步JDK额外依赖特点HttpURLConnection 【优点】Java内置,简单易用。对于简单的HTTP请求和响应处理非常合适。 【缺点】功能相对较少,不支持现代特性(如异步请求、连接池等)。API相对繁琐,处理复杂请求时代码冗长。…...

装饰模式(Decorator Pattern)在 Go 语言中的应用
文章目录 引言什么是装饰模式?在Go语言中的应用定义接口实现具体逻辑创建装饰器使用装饰器 装饰模式 vs 中间件装饰模式中间件区别 总结 引言 在软件开发中,设计模式是解决常见问题的模板。装饰模式(Decorator Pattern)是一种结构…...

Windows系统部署redis自启动服务
文章目录 引言I redis以本地服务运行(Windows service)使用MSI安装包配置文件,配置端口和密码II redis服务以终端命令启动缺点运行redis-server并指定端口和密码III 知识扩展确认redis-server可用性Installing the Service引言 服务器是Windows系统,所以使用Windows不是re…...

34岁IT男的职场十字路口:是失业预警,还是转型契机?
在信息技术这片充满机遇与挑战的广袤领域,34岁,一个看似正值壮年却暗藏危机的年龄,成为了许多IT男性不得不面对的职场考验。当“34岁现象”逐渐凸显,我们不禁要问:在这个快速变化的时代,34岁的IT男…...

复试经验分享《三、计算机学科专业基础综合》- 数据结构篇
复试经验分享 三、计算机学科专业基础综合 3.1 数据结构 3.1.1 概念 时间复杂度 时间复杂度是指执行算法所需要的计算工作量一般情况下,按照基本操作次数最多的输入来计算时间复杂度,并且多数情况下我们去最深层循环内的语句所描述的操作作为基本操作…...

数学建模算法与应用 第16章 优化与模拟方法
目录 16.1 线性规划 Matlab代码示例:线性规划求解 16.2 整数规划 Matlab代码示例:整数规划求解 16.3 非线性规划 Matlab代码示例:非线性规划求解 16.4 蒙特卡洛模拟 Matlab代码示例:蒙特卡洛模拟计算圆周率 习题 16 总结…...

windows下安装、配置neo4j并服务化启动
第一步:下载Neo4j压缩包 官网下载地址:https://neo4j.com/download-center/ (官网下载真的非常慢,而且会自己中断,建议从以下链接下载) 百度网盘下载地址:链接:https://pan.baid…...

【JVM】—深入理解G1回收器—回收过程详解
深入理解G1回收器—回收过程详解 ⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记链接👉https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点个star~😊 文章目录 深入理解G1回收…...

2、CSS笔记
文章目录 二、CSS基础CSS简介CSS语法规范CSS代码风格CSS选择器CSS基础选择器标签选择器类选择器--最常用id选择器通配符选择器 CSS复合选择器交集选择器--重要并集选择器--重要后代选择器--最常用子代选择器--重要兄弟选择器相邻兄弟选择器通用兄弟选择器 属性选择器伪类选择器…...

使用XML实现MyBatis的基础操作
目录 前言 1.准备工作 1.1⽂件配置 1.2添加 mapper 接⼝ 2.增删改查操作 2.1增(Insert) 2.2删(Delete) 2.3改(Update) 2.4查(Select) 前言 接下来我们会使用的数据表如下: 对应的实体类为:UserInfo 所有的准备工作都在如下文章。 MyBatis 操作…...

智汇云舟亮相WAFI世界农业科技创新大会,并参编数字农业产业图谱
10月10日,2024WAFI世界农业科技创新大会农食行业创新与投资峰会在北京金海湖国际会展中心举行。中国农业大学MBA教育中心主任、教授付文阁、平谷区委常委、统战部部长刘堃、华为公共事业军团数字政府首席专家刘丹、荷兰瓦赫宁根大学前校长Aalt Dijkhuizen、牧原食品…...

昇思MindSpore进阶教程--数据处理性能优化(中)
大家好,我是刘明,明志科技创始人,华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享,如果你也喜欢我的文章,就点个关注吧 shuffle性能优化 shuffle操作主要是对有…...

Vivado - Aurora 8B/10B IP
目录 1. 简介 2. 设计调试 2.1 Physical Layer 2.2 Link Layer 2.3 Receiver 2.4 IP 接口 2.5 调试过程 2.5.1 Block Design 2.5.2 释放 gt_reset 2.5.3 观察数据 3. 实用技巧 3.1 GT 坐标与布局 3.1.1 选择器件并进行RTL分析 3.1.2 进入平面设计 3.1.3 收发器布…...

图(Java语言实现)
一、图的概念 顶点(Vertex):图中的数据元素,我们称之为顶点,图至少有一个顶点(非空有穷集合)。 边(Edge):顶点之间的关系用边表示。 1.图(Graph…...

GPT 生成绘画_Java语言例子_超详细
基于spring ai :简化Java AI开发,提升效率与维护性 过去在使用Java编写AI应用时,主要困境在于缺乏统一的标准化封装,开发者需要针对不同的AI服务提供商查阅各自独立的文档并进行接口对接,这不仅增加了开发的工作量&am…...

华为OD机试 - 小朋友分组最少调整次数 - 贪心算法(Python/JS/C/C++ 2024 E卷 100分)
华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Python/JS/C/C)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,…...

数字农业与遥感监测平台
随着全球人口的增长和气候变化的挑战,农业的可持续发展变得尤为重要。数字农业作为现代农业发展的重要方向,正逐渐成为提高农业生产效率、保障粮食安全的关键手段。遥感技术作为数字农业的重要组成部分,通过监测作物生长状况、土壤湿度、病虫…...

2023年12月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 + 解析
一、单选题 1、下列程序运行的结果是?( ) print(hello) print(world) A.helloworld B.hello world C.hello world D.helloworld 正确答案:B 答案解析:本题考察的 Python 编程基础,print 在打印时…...

【优选算法】——双指针(下篇)!
🌈个人主页:秋风起,再归来~ 🔥系列专栏:C刷题算法总结 🔖克心守己,律己则安 目录 1、有效三角形的个数 2、查找总价值为目标值的两个商品 3、三数之和 4、四数之和 5、完结散花 1、有…...

C#中函数重载的说明
一.函数重载的基本概念 C# 中的函数重载是指在同一个类中定义多个同名的函数,但这些函数的参数类型、参数个数、参数顺序等不同,以便适应不同的调用需求,增加代码的兼容性。 二.函数重载的作用 2.1定义多个相类似的函数,减少函…...