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

【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. 概念

  1. 软链接概念:也称为符号链接,是一种特殊类型的独立文件,它不直接包含文件的实际内容,而是包含了指向目标文件或目录的路径,类似于Windows中的快捷方式。当访问链接时,系统会根据链接中存储的路径找到并访问目标文件或目录。

ln -s 目标路径 链接路径


在这里插入图片描述

1.2. 特点

  1. 存储内容:软链接文件不直接包含文件的实际内容,而是包含了指向目标文件或目录的路径字符串。

  2. 独立文件:软链接文件在文件系统中是一个独立文件,拥有自己的inode编号和属性。

  3. 访问方式:通过软链接访问文件或目录时,系统首先读取软链接文件中的内容(即:路径信息),然后根据该路径找到并访问实际的目标文件或目录。

  4. 跨文件系统:软链接可以跨文件系统使用,即:可以链接到不同文件系统中的文件或目录。

  5. 删除与移动:如果目标文件被删除或移动,软链接将变为无效(即:死链接),但删除软链接本身,不会影响目标文件或目录。

1.3. 应用场景

  1. 快速访问文件:当某个文件位于深层次的目录中,通过创建一个指向该文件的软链接,就可以快速访问到该文件,简化了文件访问过程。这类似于Windows中的快捷方式。

  2. 动态库版本管理:对于共享库,可以使用软链接来管理不同版本动态库之间的切换。如:创建一个指向最新版本动态库的软链接,当库升级时,仅需要更新软链接指向新版本的动态库。

2. 硬链接

2.1. 概念

  1. 硬链接概念:指多个文件名指向同一个物理文件的链接关系。这些链接在文件系统中具有相同的inode编号,但可以位于不同的目录中。

建立硬链接,并没有新建文件,而是为文件创建了新的文件名,硬链接不是一个独立的文件,因为inode与目标文件的inode相同。

  1. 硬链接本质是在指定目录下,插入新的文件名和inode之间的映射关系,并让inode中的硬链接计数++。

ln 源路径 硬链接路径

2.2. 硬链计数

一、硬链接计数的概念

  1. 概念:在linux中,每个inodo中都有一个硬链接计数,它表示有多少个文件名指向这个inode。

二、硬链接计数的变化场景

  1. 创建文件:当创建一个新文件时,这个文件的硬件计数默认为1,因为此时只要一个文件名指向这个inode。

  2. 创建硬链接:当使用ln创建一个文件的硬链接,不会创建一个新的文件,只会为该文件创建一个新的文件名,并增加inode中的硬链接计数。

  3. 删除文件:当删除一个文件时,会删除指向该文件的文件名,并减少inode中的硬链接计数,如果此时硬链接计数等于0,文件才会被删除,系统回收该inode及其所占的磁盘空间。

三、硬链接计数的限制

  1. 不能跨文件系统:硬链接只能在同一文件系统内创建,不能跨文件系统或分区,因为inode只在分区内唯一。

  2. 不支持目录:在linux中,默认情况下,不能对目录创建硬链接,否则会导致环路问题。

问:为什么目录链接计数默认不为1?

  • Linux中,每个目录都包含两个特殊的目录 “.“和”. .”,".“代表当前目录,”. ."代表上级目录,它们在目录被创建时就自动生成,并作为硬链接存在。

💡Tips:一个目录下,子目录数 = 主目录硬链接计数 - 2。

2.3. 特点

  1. 共享inode:硬链接与原始文件共享同一个inode编号,意味着它们指向同一个物理文件的数据块,对物理文件所做的任何更改都将反映在所有硬链接上。

  2. 增加访问路径:创建硬链接实际上是为文件增加了一个新的访问路径或文件名。

  3. 无差别访问:无论通过哪个文件名访问文件,都指向同一个inode,即:指向同一个文件内容。因此硬链接与原始文件无差别,二者等价。

  4. 节省空间:由于硬链接共享相同的inode和数据块,因此它们不会占用额外都磁盘空间。

  5. 删除与移动:如果删除目标文件或硬链接,只要inode中的硬链接计数不为0,文件仍可以被硬链接访问,直到硬链接计数=0,文件才被真正删除。

  6. 只能在同一文件系统(分区)内创建,不允许对目录创建硬链接。

2.4. 应用场景

硬链接应用场景如下:数据备份、数据共享、数据恢复、版本控制、自动同步等。

3. 动静态库

  1. 库文件:将多个对象文件(.o文件)打包在一起的文件。

如果我希望其他人能够使用我编写的方法,通常的方法是提供一组同名方法.o文件(预编译的对象文件),然后将所有.o文件打包形成一个库文件,和相应的同名方法.h头文件。即:库文件 + 头文件。

3.1 库存在的原因

  1. 提高开发效率。

库底层封装了重复的代码和常用的功能,使得开发者在编写项目时可以直接使用这些现成的代码,而无需从头开始编写,这大大减少了开发的时间,提高了开发效率。

  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

  1. archive-file是静态库名(lib库名.a);object-files是要添加到库中的对象名(.o文件)。

  2. 常见的选项

-c:创建库文件,如果库已存在,则会被覆盖。

-r:向库文件中添加.o文件,如果.o文件已在库中存在,则会被替换。

-t:列出库文件中包含的.o文件列表。

-v:在执行过程中显示详细的信息。

第一步:编译形成 .o 文件。

第二步:使用ar命令,将所有.o文件进行打包,形成静态库文件。

第三步:将库进行标准化。

  1. 库的标准化:通常将头文件或库文件分别放在不同的文件夹中,可以提高项目的可维护性和组织性。

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;                                                                            
}
  1. -I(i的大写):用来指定编译器搜索头文件的额外路径。

当编译器在编译过程中遇到#include指令时,它先会在标准的位置(当前目录或系统默认的头文件路径)来查找指定的头文件,如果查找不到,编译器就会使用-I指定的路径进行搜索。

  1. -L:用来指定链接器搜索库文件的额外路径。

当链接器在链接中需要找到某个库文件(.so、.a),它先会在标准的位置(系统默认的库路径)中查找,如果查找不到,链接器就会使用-L指定的路径进行搜索。

  1. -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. 库安装

  1. 将库或其他软件安装到系统中,本质是把对应的文件,拷贝到系统默认的搜索路径中。

  2. 在64位系统,系统中库默认的搜索路径为/lib64、/usr/lib64;在32系统,系统中库默认的搜索路径为/lib、/usr/lib。

4.2. 软链接

4.3. /etc/ld.so.conf.d配置文件

  1. /etc/ld.so.conf.d目录下的配置文件,用来指定额外的库文件的搜索路径,以便动态链接器能够在运行时找到并加载这些库文件。

4.4. LD_LIBRARY_PATH环境变量

  1. LD_LIBRARY_PATH:是一个环境变量,在linux中,为动态链接器指定额外的库搜索路径。

5. 动静态链接的选择

  1. 动静库同时存在:gcc默认会使用动态库进行动态链接;若想要进行静态链接,必须加上-static选项。

  1. 只存在静态库:可执行程序只能进行静态链接,程序不一定整体是静态链接的。

可执行程序只能进行静态链接,指的是对于特定库的链接方式: 当系统中只存在某个库的静态版本,任何尝试链接到这个库的程序都必须使用使用静态链接,因为动态链接器在运行时无法找到这个库的动态版本。

程序不一定整体是静态链接的,取决于它所依赖的所有库,以及编译链接时的选项: 一个程序可能依赖于多个库,此外,即使程序使用了静态链接来链接某些库时,它仍可能依赖于动态链接的库(C、C++标准库或系统库),这些库在OS级别上提供,且以动态链接的形式存在,以便在多个程序之间共享。

  1. 只存在动态库:只能进行动态链接,若非得进行静态链接,编译器或链接器会报错。

6. 理解动态库加载

6.1. 站在OS角度理解

一、动态库概念

  1. 动态库:也称为共享库,是一种包含代码和数据,可以在多个程序之间共享的文件,存放在磁盘上。

与静态库不同,静态库在程序编译时会被完全复制到可执行文件中,而共享库则在程序运行时被加载到内存中,如果多个程序使用同一个共享库,OS会让这些进程共享内存中的同一份库代码和数据,即:动态库的代码和数据在内存中只存在一份。

  1. 管理:系统中可以同时存在多个已经被加载的库,OS需要管理它们,先描述(包含了加载地址等信息)、再组织。

二、动态库加载的过程

  1. 检查依赖:程序启动时,动态链接器会检查该程序依赖的所有动态库。

  2. 搜索路径:动态链接器会在预设的库搜索路径中查找所需的动态库文件。

  3. 加载与映射:第一次加载、后续加载。

第一次加载:如果动态库尚未被加载到内存中,动态链接器会将该库加载到内存中,并映射到进程地址空间的共享区中。

后续加载:如果其他进程也需要共享这个库,动态链接器会检查内存中是否已存在该库;如果已存在,只需修改地址空间中共享区的映射关系,指向已存在的库副本;如果不存在,则重复第一次加载的过程。

  1. 优点:节省内存、易于更新、提高了程序的性能和安全性。

6.2. 编址

  1. 可执行程序在编译和链接完成后就已经具有了明确的格式信息,且在文件中按照类别划分了不同的区域 (如:代码段、未初始化数据段(BBS段)、初始化数据段),每个区域都有其对应的地址信息,通常是相对地址(虚拟地址)。

  2. 编址:在编译和链接阶段,为程序和库中的符号(变量、函数)分配地址的过程,主要有绝对编址、相对编址两种方式。

可编址的范围:32位平台,[0, 2^32] -> [0, 4GB] ,64位平台,[0, 2^64] -> [0, 16GB]。

  1. 绝对编址:在编译和链接过程中,符号的地址是固定的,即:已经确定了符号的实际的物理内存地址。这种方式要求程序运行时,必须加载到特定的物理地址处,否则无法正确的运行。

绝对编址中的地址 == 实际的物理内存地址。

在计算机早期,程序使用绝对编址,因为当时系统比较简单,程序通常使用直接映射到物理内存的绝对编址,而没有复杂的内存管理和保护机制,如:虚拟内存、页表等。

  1. 相对编制:也成为逻辑地址、虚拟地址。在编译和链接过程中,符号的地址是不固定的,而是相对于某个基地址的偏移量。这种方式允许程序在加载时动态确定实际地址,从而实现位置无关代码。

符号地址 = 基地址 + 偏移量。基地址在编译链接阶段是未知的,通常是由OS在程序加载时分配的虚拟地址,是在地址空间内的一个起始地址,如:0x400000。

现代计算机系统广泛使用相对编址,因为这提供了更好的灵活性和安全性。

问:地址空间、页表中的数据来自哪里?

  • 当基地址确定后,OS会使用可执行程序中各个区域的虚拟地址,来初始化进程地址空间、页表。每个区域在进程地址空间都有一个相对应的虚拟地址范围。在程序被加载到内存中,OS会自动分配物理内存,并构建页表来建立虚拟地址和物理地址之间的关系。

每个可执行程序大小不同,说明了每个程序中各个区域虚拟地址范围也会不同。相应地,当这些程序被加载到内存变为进程时,则每个进程地址空间中各个区域的虚拟地址的范围也是不同的。

6.3. 理解动态链接和加载问题

6.3.1. 一般程序的加载

一、一般程序加载的过程

  1. 读取可执行文件,并解析文件中各个段的信息:OS先从存储介质(如硬盘)中读取可执行文件(程序代码、数据以及依赖的库),然后OS会解析可执行文件中的各个段(如代码段、数据段、堆栈段等)的信息。这些段包含了程序运行所需的所有指令和数据。

  2. 分配虚拟地址空间、并确定基地址。

  3. 加载程序段、初始化地址空间:OS将可执行文件中的各个段加载到地址空间的相应位置。

4.重定位:在加载过程中,OS会进行重定位操作。这包括解析程序中的符号引用(如函数名、变量名等),并将它们转换为实际的物理内存地址。

  1. 初始化数据段和未初始化数据段、构建页表。

  2. 设置程序计数器(PC指针):在程序开始执行之前,OS会将PC指针设置为程序入口点的地址(main函数的地址),这是程序执行的第一条指令的虚拟地址。

  3. 执行程序:CPU会根据程序计数器中的地址从内存中读取指令,并执行它。

二、地址空间的构建和管理,需要由CPU、编译器、OS三者共同配合完成。

  1. CPU提供硬件支持,cr3寄存器存储页表的指针,MMU负责将虚拟地址转化为物理地址。

  2. 编译器负责将源代码编译成机器码,并生成可执行文件,这个文件包含了各个段的信息; 编译器在编译过程将程序中的符号地址编译成相对于基地址的偏移量;

  3. 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. 引言 在后端开发中&#xff0c;如何设计一套易于扩展、可维护且灵活的系统架构是开发者面临的重要课题。设计模式在这一过程中扮演了至关重要的角色&#xff0c;尤其是在面向对象编程中&#xff0c;它提供了大量解决重复问题的标准…...

划重点!入门安全测试,这几点要注意!

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

mysql 09 独立表空间结构

表空间中的页实在是太多了&#xff0c;为了更好的管理这些页面&#xff0c;设计 InnoDB 的大叔们提出了 区 &#xff08;英文名&#xff1a; extent &#xff09;的概念。对于16KB的页来说&#xff0c;连续的64个页就是一个 区 &#xff0c;也就是说一个区默认占用1MB空间大小。…...

linux 虚拟环境下源码安装DeepSpeed

第一步&#xff1a;创建虚拟环境&#xff1a; conda create -n deepspeed python3.10 第二步&#xff1a;进入虚拟环境&#xff0c;安装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汽车&#xff0c;搭载EA211发动机和手自一体变速器&#xff0c;累计行驶里程约为4.5万km。该车行驶中挡位偶尔会锁在D3挡&#xff0c;车速最高约50 km/h&#xff0c;且组合仪表上的发动机故障灯和EPC灯异常点亮。 故障诊断  用故障检测仪检…...

Linux之HugePage的原理与使用

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

一步步优化Redis实现分布式锁

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

C++进阶——二叉搜索树

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

Require:业界优秀的HTTP管理方案。

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

装饰模式(Decorator Pattern)在 Go 语言中的应用

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

Windows系统部署redis自启动服务

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

34岁IT男的职场十字路口:是失业预警,还是转型契机?

在信息技术这片充满机遇与挑战的广袤领域&#xff0c;34岁&#xff0c;一个看似正值壮年却暗藏危机的年龄&#xff0c;成为了许多IT男性不得不面对的职场考验。当“34岁现象”逐渐凸显&#xff0c;我们不禁要问&#xff1a;在这个快速变化的时代&#xff0c;34岁的IT男&#xf…...

复试经验分享《三、计算机学科专业基础综合》- 数据结构篇

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

数学建模算法与应用 第16章 优化与模拟方法

目录 16.1 线性规划 Matlab代码示例&#xff1a;线性规划求解 16.2 整数规划 Matlab代码示例&#xff1a;整数规划求解 16.3 非线性规划 Matlab代码示例&#xff1a;非线性规划求解 16.4 蒙特卡洛模拟 Matlab代码示例&#xff1a;蒙特卡洛模拟计算圆周率 习题 16 总结…...

windows下安装、配置neo4j并服务化启动

第一步&#xff1a;下载Neo4j压缩包 官网下载地址&#xff1a;https://neo4j.com/download-center/ &#xff08;官网下载真的非常慢&#xff0c;而且会自己中断&#xff0c;建议从以下链接下载&#xff09; 百度网盘下载地址&#xff1a;链接&#xff1a;https://pan.baid…...

【JVM】—深入理解G1回收器—回收过程详解

深入理解G1回收器—回收过程详解 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; 文章目录 深入理解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) 前言 接下来我们会使用的数据表如下&#xff1a; 对应的实体类为&#xff1a;UserInfo 所有的准备工作都在如下文章。 MyBatis 操作…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...