分散加载文件 scatter files

news2024/12/24 2:31:35

目录

  • 一、加载域和执行域
  • 二、Image entry points
  • 三、映射符号
  • 四、链接器预定义符号
    • 1、将符号引入到程序中
      • 1.1 引入到 C/C++
      • 1.2 引入到汇编
    • 2、域相关的符号
      • 2.1 执行域符号 `Image$$`
      • 2.2 执行域符号 `Load$$`
      • 2.3 加载域符号 `Load$$LR$$`
      • 2.4 节相关的符号
      • 2.5 镜像符号
      • 2.6 输入节符号
  • 五、分散加载机制
  • 六、根执行域
  • 七、未初始化变量的定义方法


本文主要是对 浅析 Keil 中的 sct 文件 一文做进一步的补充和说明。

一、加载域和执行域

镜像的各个域在加载时是被放置在系统存储器中的。 在执行镜像之前,可能必须将一些域移动到它们的执行地址,并创建 ZI 输出节。例如,初始化的 RW 数据可能必须从 ROM 中的加载地址复制到 RAM 中的执行地址。为了可以灵活的处理这种情况,ARM 定义了如下两个视图:

  • Load view: 根据镜像在加载到内存中时所位于的地址(镜像执行开始前的位置),描述每个镜像域和节。
  • Execution view: 根据镜像执行过程中所位于的地址,描述每个镜像域和节。

下面是两种视图的对比:

LoadDescriptionExecutionDescription
加载地址在包含分节或域的镜像开始执行之前,要加载到内存中的节或者域的地址。
节或者非根域的加载地址和他们执行地址可以不同
执行地址当包含某个节或域的镜像被执行时,该节或域所在的地址
加载域加载域描述在加载地址空间中连续内存块的布局执行域执行域描述在执行地址空间中的连续内存块的布局

二、Image entry points

镜像中入口点(Image entry points)就是镜像中的一个位置(地址),该位置(地址)会被加载到 PC 寄存器。 它是程序执行开始的位置。 虽然镜像中可以有多个入口点,但在链接时只能指定一个入口点。并非每个 ELF 文件都必须有入口点。 不允许在单个 ELF 文件中存在多个入口点。

对于嵌入式 Cortex-M 核的程序,程序的执行是从复位向量所在的位置(地址)开始执行。复位向量会被加载到 PC 寄存器中,且复位向量的位置(地址)并不固定。 通常,复位向量指向 Reset_Handler 函数。

有两种不同类型的入口点:

  • 初始化入口点(Initial entry point): 镜像的初始入口点是存储在 ELF 头文件中的单个值。 对于那些需要由操作系统或引导加载程序加载到 RAM 中的程序,加载程序通过将控制转移到镜像中的初始入口点来启动镜像执行。一个镜像只能有一个初始化入口点。初始入口点可以是 ENTRY 指令设置的入口点之一,但不是必需的。
  • ENTRY 指令指定的入口点: ENTRY 指令可以为镜像从多个可能的入口点中选择其中一个。每个镜像只能有一个入口点。您可以在汇编程序文件中使用 ENTRY 指令在对象中创建入口点。 在嵌入式系统中,该指令的典型用途是标记进入处理器异常向量(例如 RESET,IRQ 和 FIQ)的代码。该指令使用 ENTRY 关键字标记输出代码部分,该关键字指示链接器在执行未使用的部分消除时不删除该部分。对于 C/C++ 程序,C 库中的 __main 就是入口点。

如果加载程序要使用嵌入式的镜像,则它必须在标头中指定一个初始入口点。 使用 --entry 命令行选项选择入口点。

三、映射符号

映射符号由编译器汇编器生成,以识别文字池边界处的代码和数据之间的内联转换,以及 ARM 代码和 Thumb 代码之间的内联转换。例如 ARM/Thumb 交互操作胶合代码。其必须由 armlink 的参数 --list_mapping_symbols--no_list_mapping_symbols 分别来控制显示与不显示。在默认情况下为 `–no_list_mapping_symbols,即不显示这部分符号。映射符号有如下这些:

  • $a:一系列 ARM 指令的开始
  • $t:一系列 Thumb 指令的开始
  • $t.x:一系列 ThumbEE 指令的开始
  • $d:一系列数据项的开始,如文字池

补充说明:

  1. 文字池:是代码段中存放常量数据的区域。因为没有一条指令可以生成一个 4 字节的常量,因此编译器将这些常量放到文字池中,然后生成从文字池加载这些常量的代码。
  2. ARM/Thumb交互ARM/Thumb interworking):是指对汇编语言和 C/C++ 语言的 ARM 和 Thumb 代码进行连接的方法,它进行两种状态(ARM 和 Thumb)间的切换。
  3. 胶合代码Veneer):在进行 ARM/Thumb 交互时,有时需使用额外的代码,这些代码被称为 胶合代码(Veneer)。
  4. AAPCS:定义了 ARM 和 Thumb 过程调用的标准。

此外, armlink 还会生成 $d.realdata 映射符号,以告诉 fromelf 该数据是来自非可执行节区。因此, fromelf -z 输出的代码和数据大小与 armlink --info sizes 的输出相同。

四、链接器预定义符号

当链接器创建镜像文件时,它会创建一些 ARM 预定义的与域或者节相关的符号。这些符号就代表了链接器创建创建镜像的依据。

链接器定义了一些 ARM 保留的符号,我们可以在需要时访问这些符号。 这些符号是包含 $$ 字符序列的符号以及所有其他包含 $$ 字符序列的外部名称。我们可以导入这些符号地址,并将它们作为汇编语言程序的可重定位地址使用,或者将它们作为 C 或 C++ 源代码中的 extern 符号来引用。

如果使用 --strict 编译器命令行选项,则编译器不接受包含 $ 的符号名称。要重新启用支持,请在编译器命令行中包含 --dollar 选项。

  • 链接器定义的符号只有在代码引用它们时才会生成。
  • 如果存在仅执行(XO)节,则链接器定义的符号受以下约束:
    • 不能对没有 XO 节的域或者空域定义 XO 连接器定义符号
    • 不能对仅包含 RO 节的域定义 XO 连接器定义符号
    • 对于仅包含 XO 节的域,不能定义 RO 连接器定义符号

1、将符号引入到程序中

1.1 引入到 C/C++

可以通过 值引用 或 地址引用 这两种方式将链接器定义的符号导入到的 C 或 C++ 源代码中来供我们使用:

  • 值引用:extern unsigned int symbol_name;
  • 地址引用:extern void *symbol_name;

注意,如果将符号声明为 int 类型的值引用,则必须使用寻址操作符(&)来获得正确的值,如下例所示:

// Importing a linker-defined symbol
extern unsigned int Image$$ZI$$Limit;
config.heap_base = (unsigned int) &Image$$ZI$$Limit;

// Importing symbols that define a ZI output section
extern unsigned int Image$$ZI$$Length;
extern char Image$$ZI$$Base[];
memset(Image$$ZI$$Base, 0, (unsigned int)&Image$$ZI$$Length);

1.2 引入到汇编

可以使用指令 IMPORT 将连接器定义的符号引入到 ARM 汇编文件中来供我们使用:

IMPORT |Image$$ZI$$Limit|
...
zi_limit DCD |Image$$ZI$$Limit|

LDR r1, zi_limit

2、域相关的符号

链接器为镜像文件中的每个域生成不同类型的与域相关的符号,我们可以根据需要访问这些符号。域相关的符号主要有以下两种:

  • Image$$ 或者 Load$$ 开头的符号,用于各执行域
  • Load$$LR$$ 开头的符号,用于各加载域

如果未使用分散加载文件,则会以默认的 region 名称来生成域相关的符号。链接器默认的域名称如下:

  • ER_XO :用于仅执行属性的执行域(如果存在)。
  • ER_RO :用于只读执行域。
  • ER_RW :用于可读写执行域。
  • ER_ZI :用于零初始化的执行域。

可以将这些名称插入 Image$$Load$$ 中以获取所需的地址,例如:Load$$ER_RO$$Base 就是只读域的基地址。

使用分散加载时,连接器将使用分散加载文件中的名称来生成各种域相关的符号。分散加载文件可以实现以下功能:

  • 命名镜像中的所有执行域,并提供他们的加载和执行地址。
  • 定义堆栈和堆。 链接器还会生成特殊的栈和堆符号。

注意一下几点:

  1. 镜像的 ZI 输出节不是静态创建的,而是在运行时自动动态创建的。 因此,ZI 输出节没有加载地址符号。
  2. 符号 Load$$region_name 仅适用于执行域。Load$$LR$$load_region_name 符号仅适用于加载域。

2.1 执行域符号 Image$$

链接器为镜像中存在的每个执行域生成符号 Image$$。下表列出了链接器为镜像中存在的每个执行域生成的符号。 初始化 C 库后,所有符号都指向执行地址。

SymbolDescription
Image$$region_name$$Base执行域的地址
Image$$region_name$$Length执行域长度(以字节为单位),不包括 ZI 的长度。
Image$$region_name$$Limit超出执行域中非 ZI 部分末尾的字节的地址
Image$$region_name$$RO$$Base域中的输出节 RO 的执行地址
Image$$region_name$$RO$$LengthRO 段输出部分的长度(字节)
Image$$region_name$$RO$$Limit执行域中 RO 输出部分末尾以外字节的地址
Image$$region_name$$RW$$Base该域中 RW 输出部分的执行地址
Image$$region_name$$RW$$LengthRW 输出部分的长度(字节)
Image$$region_name$$RW$$Limit执行域中 RW 输出部分末尾以外字节的地址
Image$$region_name$$XO$$Base该域内 XO 输出部分的执行地址
Image$$region_name$$XO$$LengthXO 输出部分的长度(字节)
Image$$region_name$$XO$$Limit执行域中 XO 输出部分末端以外字节的地址
Image$$region_name$$ZI$$Base该域 ZI 输出部分的执行地址
Image$$region_name$$ZI$$LengthZI 输出部分的长度(字节)
Image$$region_name$$ZI$$Limit执行域中 ZI 输出部分末端以外字节的地址

2.2 执行域符号 Load$$

链接器为镜像中存在的每个执行域生成符号 Load$$ 。下表列出了链接器为镜像中存在的每个 Load$$ 执行域生成的符号。 初始化 C 库后,所有符号都指向加载地址。

SymbolDescription
Load$$region_name$$Base 加载域地址
Load$$region_name$$Length该域长度(字节)
Load$$region_name$$Limit执行域末端以外字节的地址
Load$$region_name$$RO$$Base该执行域中 RO 输出部分的地址
Load$$region_name$$RO$$LengthRO 输出部分的长度(字节)
Load$$region_name$$RO$$Limit执行域中 RO 输出部分末尾以外字节的地址
Load$$region_name$$RW$$Base该执行域中 RW 输出部分的地址
Load$$region_name$$RW$$LengthRW 输出部分的长度(字节)
Load$$region_name$$RW$$Limit执行域中 RW 输出部分末尾以外字节的地址
Load$$region_name$$XO$$Base该执行域中 XO 输出部分的地址
Load$$region_name$$XO$$LengthXO 输出部分的长度(字节)
Load$$region_name$$XO$$Limit执行域中 XO 输出部分末端以外字节的地址
Load$$region_name$$ZI$$Base该执行域中 ZI 输出部分的加载地址
Load$$region_name$$ZI$$LengthZI 输出部分的加载长度(字节)。
除非 region_name 具有 ZEROPAD 分散加载关键字,否则 ZI 的加载长度为零。
如果设置了 ZEROPAD 则:
Load Length = Image$$region_name$$ZI$$Length
Load$$region_name$$ZI$$Limit执行域 ZI 输出部分末端以外字节的加载地址

初始化 C 库之前,此表中的所有符号均指加载地址。请注意以下事项:

  1. 这些符号是绝对的,因为相对于节的符号只能有执行地址。
  2. 这些符号考虑了 RW 压缩。
  3. 从 RW 压缩执行域引用的链接器定义的符号必须是在应用 RW 压缩之前可解析的符号。
  4. 如果链接器检测到从 RW 压缩域到依赖于 RW 压缩的链接器定义符号的重定位,则链接器将禁用当前域的压缩。
  5. Limit 和 Length 值影响写入文件的任何零初始化数据。 使用 ZEROPAD 分散加载关键字时,零初始化数据将写入文件。

2.3 加载域符号 Load$$LR$$

链接器为镜像中存在的每个加载区生成符号 Load$$LR$$ 。一个 Load$$LR$$ 加载域可以包含许多执行域,因此没有单独的 $$RO$$RW 部分。下表显示了链接器为镜像中存在的每个 Load$$LR$$ 加载域生成的符号。

SymbolDescription
Load$$LR$$load_region_name$$Base加载域的地址
Load$$LR$$load_region_name$$Length加载域的长度
Load$$LR$$load_region_name$$Limit加载域末端以外字节的地址

2.4 节相关的符号

与节相关的符号是链接器在创建没有使用分散加载文件的镜像时生成的符号。链接器会为输出和输入节生成不同类型的与节相关的符号:

  • 镜像符号(Image symbols)(如果不使用分散加载来创建简单的镜像文件)。 简单的镜像文件具有多达四个输出节(XO,RO,RW 和 ZI),用于生成相应的执行域。
  • 输入节符号(Input section symbols) 镜像中存在的每个输入节的输入节符号(Input section symbols

链接器首先按属性 RO,RW 或 ZI 对执行域内的节进行排序,然后按名称排序。 例如,所有 .text 节都放在一个连续的块中。 具有相同属性和名称的连续块部分称为合并节。

ARM 建议优先使用与域相关的符号,而不是与节相关的符号。

2.5 镜像符号

当不使用分散加载文件来创建简单镜像时,镜像符号将由链接器生成。我们常用的 Keil 会默认生成分散加载文件的,所以基本没有不使用分散加载文件的情况。下表显示了镜像符号:

SymbolSection typeDescription
Image$$RO$$BaseOutputRO 输出部分的起始地址
Image$$RO$$LimitOutput超出 RO 输出部分末尾的第一个字节的地址
Image$$RW$$BaseOutputRW 输出部分的起始地址
Image$$RW$$LimitOutput超出 ZI 输出部分末端的字节地址
(选择 ZI 区域的末端而不是 RW 区域的末端,是为了保持与传统代码的兼容性)
Image$$ZI$$BaseOutputZI 输出部分的起始地址
Image$$ZI$$LimitOutput超出 ZI 输出部分末端的字节地址

如果存在 XO 节,那么还包含符号 Image$$XO$$BaseImage$$XO$$Limit

如果使用了分散加载文件,则上面这些镜像符号都将称为未定义的。 如果在代码中访问这些符号中的任何一个,则必须将它们视为弱引用(__weak__) 。__user_setup_stackheap() 的标准实现中就使用 Image$$ZI$$Limit 中的值,因此,如果您使用的是分散加载文件,则必须手动设置堆栈和堆。 方法主要有以下两种:

  • 在分散文件中使用下列方法之一
    • 定义名为 ARM_LIB_STACKARM_LIB_HEAP 的单独的栈和单独的堆域。
    • 定义包含堆栈和堆的组合域,名为 ARM_LIB_STACKHEAP
  • 通过重新实现 __user_setup_stackheap() 来设置堆和堆栈边界。(在 STM32 的 .s 启动文件中,正是用的这种方法)

2.6 输入节符号

链接器为镜像中存在的每个输入节生成输入节符号。下表显示了链接器定义的输入节符号:

SymbolSection typeDescription
SectionName$$BaseInput称为SectionName的合并节的起始地址
SectionName$$LengthInput称为SectionName的合并节的长度(以字节为单位)
SectionName$$LimitInput称为SectionName的合并节末尾以外的字节的地址

如果在你的代码引用输入节符号,则表示希望将镜像中具有相同名称的所有输入节都连续放置在镜像内存映射中。如果分散加载文件不连续地放置输入节,则链接器会发出错误。 这是因为在非连续存储器上将导致 Base 符号和 Limit 符号是不明确的。

五、分散加载机制

镜像的内存映射由域和输出节组成。内存映射中的每个域可以具有不同的加载和执行地址。分散加载机制是 ARM 连接器 armlink 定义的一种特性。通过该机制,我们可以让连接器完全按照我们自己的描述来组织镜像文件的内存映射,以适应复杂的嵌入式环境。

经过前面的介绍,相信大家对分散加载有了一定的认识。所谓的分散加载就是,在加载和执行时,多个内存域分散在内存映射中

分散加载机制规定需要把我们的要求描述在一个文本文件中,这个文件被称为 分散加载文件。armlink 通过参数 --scatter “分散加载文件名” 来引用我们的分散加载文件(在 ARM 官方文档中叫做 Scatter File)。

对于简单的内存映射,可以使用以下与内存映射相关的连接器命令行( --partial--ro_base--rw_base--ropi--rosplit--split--reloc--startup--xo_base--zi_base )参数来放置代码和数据。例如,如下的内存映射,我们可以使用连接器参数 armlink --ro_base 0x0 --rw_base 0x10000 来实现。

当然,也可以使用分散加载来实现,下面的示例显示了相应的分散加载描述,该描述将对象文件中的段加载到内存中:

LOAD_ROM 0x0000 0x8000       ; Name of load region (LOAD_ROM),
                             ; Start address for load region (0x0000),
                             ; Maximum size of load region (0x8000)
{
    EXEC_ROM 0x0000 0x8000   ; Name of first exec region (EXEC_ROM),
                             ; Start address for exec region (0x0000),
                             ; Maximum size of first exec region (0x8000)
    {
        * (+RO)              ; Place all code and RO data into
                             ; this exec region
    }
    SRAM 0x10000 0x6000      ; Name of second exec region (SRAM),
                             ; Start address of second exec region (0x10000),
                             ; Maximum size of second exec region (0x6000)
    {
        * (+RW, +ZI)         ; Place all RW and ZI data into
                             ; this exec region
    }
}

但需要注意,参数 --scatter "分散加载文件名" 是不能与上面这些一起使用的!

分散加载通常只用于具有复杂内存映射的镜像中。对于具有复杂内存映射的镜像,不能仅使用链接器命令行选项指定内存映射。

如上图所示的内存映射,下面的示例显示了对应的分散加载描述,该描述将来自 program1.oprogram2.o 文件的段加载到内存中:

LOAD_ROM_1 0x0000              ; Start address for first load region (0x0000)
{
    EXEC_ROM_1 0x0000          ; Start address for first exec region (0x0000)
    {
        program1.o (+RO)       ; Place all code and RO data from
                               ; program1.o into this exec region
    }
    DRAM 0x18000 0x8000        ; Start address for this exec region (0x18000),
                               ; Maximum size of this exec region (0x8000)
    {
        program1.o (+RW, +ZI)  ; Place all RW and ZI data from
                               ; program1.o into this exec region
    }
}
LOAD_ROM_2 0x4000              ; Start address for second load region (0x4000)
{
    EXEC_ROM_2 0x4000
    {
        program2.o (+RO)       ; Place all code and RO data from
                               ; program2.o into this exec region
    }
    SRAM 0x8000 0x8000
    {
        program2.o (+RW, +ZI)  ; Place all RW and ZI data from
                               ; program2.o into this exec region
    }
}

六、根执行域

有关分散加载文件的编写格式在 浅析 Keil 中的 sct 文件 已经讲过,这里不再赘述

所谓根执行域指的是加载域和执行域地址相同区域,程序入口必须在根域中,特别是 IDE 封装起来的一些文件和函数,比如 Flash 中的数据复制到 RAM 里的函数(__main)。

像上文中出现的 *(InRoot$$Sections) 就表示的是根执行域。这个段出自 C 标准库函数 __main。它的主要作用是 COPY RW 区到RAM,然后在 RW 区后面创建 ZI 区。

我们有以下方式指定根执行域:

  1. 强制指定执行域的基地址 = 加载域的基地址。例如:
LR_1 0x040000          ; load region starts at 0x40000   
{                      ; start of execution region descriptions       
    ER_RO 0x040000     ; load address = execution address
    {
        * (+RO)        ; all RO sections (must include section with 
                       ; initial entry point)
    }
    ...                ; rest of scatter-loading description
}
  1. 为加载域中的第一个执行域指定 +0 偏移量。例如:
LR_1 0x040000          ; load region starts at 0x40000   
{                      ; start of execution region descriptions      
    ER_RO +0     	   ; +offset
    {
        * (+RO)        ; all RO sections (must include section with 
                       ; initial entry point)
    }; rest of scatter-loading description
}

如果为加载域中的所有后续执行域指定了 0(+0) 的偏移量,那么所有不在包含 ZI 的执行域后面的执行域也都是根执行域。

  1. 对执行域使用 FIXED 属性,以创建在固定地址加载和执行的根执行域。例如:
LR_1 0x040000              ; load region starts at 0x40000   
{                          ; start of execution region descriptions      
    ER_RO 0x040000         ; load address = execution address
    {
        * (+RO)            ; RO sections other than those in init.o
    }
    ER_INIT 0x080000 FIXED ; load address and execution address of this
                           ; execution region are fixed at 0x80000
    {
        init.o(+RO)        ; all RO sections from init.o
    }; rest of scatter-loading description
}

可以用它来把一个函数或一个数据块,比如一个常量表或一个校验和,放在 ROM 中的一个固定地址上,这样就可以很容易地通过指针访问它。

七、未初始化变量的定义方法

现在,我有一段内存不想被初始化。在分散文件中,我将这个内存区域标记为 UNINIT,并使用 __attribute__((section(""))) 将变量放在 UNINIT 区域中,见下:

LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 UNINIT 0x00000100  { ;no init section
        *(NoInit)
   }
  RW_IRAM2 0x20000100 0x0000FFF0  {                ;all other rw data
        .ANY(+RW +ZI)
  }
}
unsigned long NI_longVar __attribute__( ( section( "NoInit") ) ) ;


int main( void )
{
  while( 1 )
  {
  }
}

原因如下:

  1. 只有具有 UNINIT 属性的执行区域中的 ZI 数据没有被初始化。然而,具有 UNINIT 属性的执行区域中的任何 RW 数据都会被初始化。
  2. ARM Compiler 5 出于优化的原因,默认将 8 字节或更少的全局 ZI 变量放入 RW 数据段。由于上述代码示例中的变量小于 8 字节,因此将其从 ZI 更改为 RW,这将导致进行初始化。

解决办法如下:

  • 在使用 ARM Compiler 5 时,为该变量添加 zero_init 属性以防止优化。这将保持变量为不初始化的 ZI 数据。
unsigned long NI_longVar __attribute__( ( section( "NoInit"), zero_init) ) ;

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

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

相关文章

HarmonyOS鸿蒙 Next 实现协调布局效果

HarmonyOS鸿蒙 Next 实现协调布局效果 ​ 假期愉快! 最近大A 的涨势实在是红的让人晕头转向,不知道各位收益如何,这会是在路上,还是已经到目的地了? 言归正传,最近有些忙,关于鸿蒙的实践系列有些脱节了,…

Electron 是如何工作的

1. 创建electron项目 pnpm init pnpm add -D electron修改配置项 package.json {"name": "electron-menu","version": "1.0.0","description": "","main": "main.js", // eletron入口&quo…

【重学 MySQL】四十七、表的操作技巧——修改、重命名、删除与清空

【重学 MySQL】四十七、表的操作技巧——修改、重命名、删除与清空 修改表添加字段语法示例注意事项 删除字段语法示例 修改字段使用 MODIFY COLUMN语法示例 使用 CHANGE COLUMN语法示例 重命名表语法示例 删除表语法示例 清空表使用 TRUNCATE TABLE使用 DELETE FROM对比 TRUNC…

聊聊晶圆厂中的常见口语(1)

知识星球里的学员问:半导体公司的工程师总爱用一些英语代替中文,比如care,show,用这种简单的单词代替中文,能不能给我们总结工程师常用的英语单词,比较口语化的! 为什么晶圆厂会用很多英文口语&#xff1f…

华为---以太网静态路由配置使用下一跳通信正常,而使用出接口无法通信

目录 1. 实验环境 2. 结果测试 3. 分析验证 3.1 以太网静态路由配置使用下一跳跨网段通信抓包分析 3.2 以太网静态路由配置使用出接口跨网段通信抓包分析 3.3 以太网静态路由配置使用出接口无法跨网段通信问题解决办法 1. 实验环境 以太网静态路由配置使用下一跳跨网段通…

番茄成熟度检测系统源码分享

番茄成熟度检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…

Opencv第十一章——视频处理

1. 读取并显示摄像头视频 1.1 VideoCapture类 VideoCapture类提供了构造方法VideoCapture(),用于完成摄像头的初始化工作,其语法格式如下: capture cv2.VideoCapture(index) 参数说明: capture:要打开的摄像头视频。 index:摄像头设备索引。…

【区间dp】AT_dp_l 题解

题意 给一个双端队列,双方轮流取数,每一次能且只能从队头或队尾取数,取完数后将这个数从队列中弹出。双方都希望自己取的所有数之和尽量大,且双方都以最优策略行动,假设先手取的所有数之和为 X X X,后手取…

【Git】一文看懂Git

Git 一、简介1. Git 与 SVN 区别1.1 Git 是分布式的,SVN 不是1.1.1 分布式版本控制系统Git1.1.2 集中式版本控制系统SVN 1.2 Git 把内容按元数据方式存储,而 SVN 是按文件1.3 Git 分支和 SVN 的分支不同1.4 Git 没有一个全局的版本号,而 SVN …

五.运输层

目录 5.1概述 5.2传输层的寻址与端口 熟知端口号 套接字(Socket) 5.3 UDP 特点 UDP报文格式 UDP校验 二进制反码求和 5.4 TCP 特点 可靠传输 停止等待协议 流水线方式 累计应答 流量控制 滑动窗口 拥塞控制 三次握手,四次握手 5.1概述 只有主机…

Pikachu-Cross-Site Scripting-反射型xss(get)

存储型XSS 存储型XSS是指恶意脚本被存储在目标服务器上,当用户访问包含该脚本的页面时,脚本会被执行。攻击者通常通过输入框、留言板等用户可输入的地方进行注入。例如,攻击者可以在留言板中输入恶意脚本,当其他用户查看留言时&a…

3.基于分数的生成模型

1.简介 基于分数的生成模型(SGM)的核心是Stein分数(或分数函数)。给定一个概率密度函数p(x),其分数函数定义为对数概率密度的梯度Vxlogp(x)。生成模型通过学习并建模输入数据的分布,从而采集生成新的样木,该模型广泛运用于图片视频生成、文本…

假期惊喜,收到公司款项86167.14元

假期惊喜 近日,有网友爆料称,比亚迪在未提前通知员工的情况下,突然发放了利润奖金。 有人获得了七八万元,也有人拿到了十多万元。 一位比亚迪员工的帖子显示,在9月26日下午,他的银行卡突然收到一笔 86167.1…

数字化那点事:一文读懂数字孪生

一、数字孪生的定义 数字孪生(Digital Twin)是指通过数字技术构建的物理实体的虚拟模型,能够对该实体进行全方位、动态跟踪和仿真预测。简单来说,数字孪生就是在一个设备或系统的基础上创造一个数字版的“克隆体”,这…

Redis --- 第二讲 --- 特性和安装

一、背景知识 Redis特性: Redis是一个在内存中存储数据的中间件,用于作为数据库,作为缓存,在分布式系统中能够大展拳脚。Redis的一些特性造就了现在的Redis。 在内存中存储数据,通过一系列的数据结构。MySQL主要是通…

Ollama安装部署CodeGeeX4 - ALL - 9B

一、模型本地部署准备 1、 conda create -n ollama python3.82、 curl -fsSL https://ollama.com/install.sh | sh3、验证安装 安装完成后,通过运行以下命令来验证Ollama是否正确安装: ollama --version4、启动ollama ollama serve模型地址&#xff…

【重学 MySQL】四十八、DCL 中的 commit 和 rollback

【重学 MySQL】四十八、DCL 中的 commit 和 rollback commit的定义与作用rollback的定义与作用使用场景相关示例注意事项DDL 和 DML 的说明 在MySQL中,DCL(Data Control Language,数据控制语言)用于管理数据库用户和控制数据的访问…

Ubuntu 安装RUST

官方给的是这样如下脚本 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh 太慢了 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh -x 执行这个脚本后会给出对应的下载链接 如下图 我直接给出来 大多数应该都是这个 https://static.rust-…

初识算法 · 双指针(1)

目录 前言: 双指针算法 题目一: ​编辑 题目二: 前言: 本文作为算法部分的第一篇文章,自然是少不了简单叭叭两句,对于算法部分,多刷是少不了,我们刷题从暴力过度到算法解法,自…

csp-j模拟二补题报告

目录传送门 前言第一题下棋(chess)我的代码(AC了)AC代码 第二题汪洋(BigWater)我的代码(0)AC代码 第三题删数(delnum)我的代码(0)AC代…