ELF文件格式解析

news2024/12/26 0:40:18

ELF文件是什么?

ELF是Executable and Linkable Format的缩写,字面上看就是可执行和可连接文件。在Linux下可重定位文件(.o)、可执行文件、共享目标文件(.so)、核心转储问文件(core dump) 都是使用ELF文件格式。

ELF 通常由编译器或者连接器产生,并且是二进制格式,使用一些工具可以更好的观察它的结构,如readelf、objdump

ELF由什么组成

ELF文件由ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)4个部分组成。
在这里插入图片描述
除了ELF头,ELF文件不一定包含其他部分,且位置分布也不一定和上图一致。

分析ELF前置准备

int printf(const char *, ...);
  
int global_init_var = 84;
int global_uninit_var;

void func1(int i){
    printf("func1 %d", i);
}

int main(){
    static int static_var = 5;
    static int static_var2;

    int a = 1;
    int b;

    func1(11 + 22 + 33 + a - b);

    return a;
}

后续会使用上面的代码产生的可重定位文件进行ELF文件的分析,产生可重定位文件的方式是gcc -c

ELF Header

ELF头的结构定义在elf.h的ELF32_Ehdr/ELF64_Ehdr中,这边以Elf64_Ehdr为例子

typedef struct
{
  unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
  Elf64_Half    e_type;         /* Object file type */
  Elf64_Half    e_machine;      /* Architecture */
  Elf64_Word    e_version;      /* Object file version */
  Elf64_Addr    e_entry;        /* Entry point virtual address */
  Elf64_Off e_phoff;        /* Program header table file offset */
  Elf64_Off e_shoff;        /* Section header table file offset */
  Elf64_Word    e_flags;        /* Processor-specific flags */
  Elf64_Half    e_ehsize;       /* ELF header size in bytes */
  Elf64_Half    e_phentsize;        /* Program header table entry size */
  Elf64_Half    e_phnum;        /* Program header table entry count */
  Elf64_Half    e_shentsize;        /* Section header table entry size */
  Elf64_Half    e_shnum;        /* Section header table entry count */
  Elf64_Half    e_shstrndx;     /* Section header string table index */
} Elf64_Ehdr;

使用readelf对之前的.o文件其进行分析

>> readelf -h main.o 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          1048 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 12

将上述输出与Elf64_Ehdr结构进行对应

字段对应Elf64_Ehdr的结构描述
Magice_ident前4个字节固定是 7F 45 4C 46; 45 4C 46 是ELF的ascii码;
Classe_ident[4]01为32位,02为64位
Datae_ident[5]01 是小端序, 02 是大端序
Versione_ident[6]表示ELF的版本号,不过一般都为1,因为ELF1.2版本后到目前都没有更新
OS/ABIe_ident[7]表示使用的ABI类型,不过一般情况下是0, 也就是UNIX - System V
ABI VERSIONe_ident[8]表示使用的ABI的版本,一般情况下是0
Typee_type表示ELF的文件类型,ET_REL(1)为可重定位文件,一般是.o文件;ET_EXEC(2)为可执行文件;ET_DYN(3)一般为.so文件; ET_CORE(4) 为core file,也就是core dump 产生的文件
Machinee_machine常量定义也在elf.h中,数量得有点多,其中EM_x86_64 为62
Versione_version意义和上面的Version一致
Entry point addresse_entry表示程序执行的入口地址,因为这边是.o文件所以该值为0
Start of program headerse_phoff表示Program Header的入口偏移量
Start of section headerse_shoff表示Section Header的入口偏移量
Flagse_flags表示ELF文件相关的特定处理器的flag
Size of this headere_ehsize表示ELF Header大小, 当前header的大小就是64 字节
Size of program headerse_phentsize表示Program Header大小
Size of section headers实际上这里指的是Elf64_Shdr这个结构的大小
Number of section headerse_shnum表示Section Header的个数
Section header string table indexe_shstrndx段表字符串表所在段在段表中的下标

这边还可以使用hexdump 来查看.o文件的前64个字节来对比readelf的输出

>>hexdump -C -n 64 main.o 
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  01 00 3e 00 01 00 00 00  00 00 00 00 00 00 00 00  |..>.............|
00000020  00 00 00 00 00 00 00 00  18 04 00 00 00 00 00 00  |................|
00000030  00 00 00 00 40 00 00 00  00 00 40 00 0d 00 0c 00  |....@.....@.....|
00000040

段表Section Header Table

ELF中包含各种各样的段,而段表就是描述这些段的基本属性的结构,如段名、段长、段在文件中的偏移、读写权限等。而段表所在的位置由Elf64_Ehdr中的e_shoff来决定。换句话说编译器、加载器、链接器等都是依靠ELF文件的段表来访问各个段的。

这边先看段表的结构,实际上段表是一个以Elf64_Shdr为元素的数组,而Elf64_Shdr结构如下:

typedef struct
{
  Elf64_Word    sh_name;        // section_name段名,实际上名字存储在字符串表'.shstrtab'中,这边存的是段名在字符串表中的下标
  Elf64_Word    sh_type;        //section type 段的类型,具体枚举后续会有
  Elf64_Xword   sh_flags;       //section flag 段的标志位,具体枚举后续会有
  Elf64_Addr    sh_addr;        //section addr  段的虚拟地址,如果该段可被加载,则会被加载到地址空间的对应虚拟地址中
  Elf64_Off sh_offset;      // section offset 段在文件中的偏移
  Elf64_Xword   sh_size;        // section size 段的长度
  Elf64_Word    sh_link;        //  section Link 段的链接信息
  Elf64_Word    sh_info;       //   section Info 段的信息
  Elf64_Xword   sh_addralign;     // Section alignment 段对齐长度,某些段会对地址对齐有要求
  Elf64_Xword   sh_entsize;     // Entry size if section holds table 某些段会有固定大小的项,这些项所占用的大小是一样的。如果为0,则不没有包含这种项
} Elf64_Shdr;

section type

段的类型相关常量都是以SHT_开头,以下是常用的段以及对应的描述

常量描述
SHT_NULL0无效
SHT_PROGBITS1代码段、数据段都是这个类型
SHT_SYMTAB2该段内容是符号表
SHT_STRTAB3该段内容是字符串表
SHT_RELA4重定位表,该段包含重定位信息
SHT_HASH5符号表的哈希表
SHT_DYNMIC6动态链接信息表
SHT_NOTE7提示性信息
SHT_NOBITS8表示该段在文件中不存在内容,.bss段就是该类型的
SHT_REL9重定位表,该段包含重定位信息
SHT_SHLIB10保留
SHT_DNYSYM11动态链接符号表

还有很多段类型的常量没展现, 具体可以看elf.h;SHT_REL(Relocation entries, no addends) 和 SHT_RELA(Relocation entries with addends) 都是重定位表,但有少许区别,对于静态编译的重定位而言,重定位地址总时相对于某个参照物进行偏移,而SHT_REL 将偏移放在了需要重定位的内存地址处,而SHT_RELA 将偏移放在了重定位表中,而重定位内存处则填0.

section flag

段的标志位相关常量是以SHF_开头,以下是常用的段的标志位

常量描述readelf 的标志
SHF_WRITE1<< 0表示该段可写入W
SHF_ALLOC1 << 1表示该段在执行时需要分配空间,如代码段、数据段、.bss段都会有这个标志A
SHF_EXECINSTR1 << 2表示该段可以被执行, 一般是指代码段X
SHF_MERGE1 << 4表示可以合并以消除重复的数据的sectionM
SHF_STRINGS1 << 5标识由NULL结尾的字符串组成的section,每个字符串的大小在section header的sh_entsize指定S
SHF_INFO_LINK1 << 6表示字段sh_info中包含section headers的某个section的下标I
SHF_LINK_ORDER1 << 7表示链接器添加了特殊的排序要求L
SHF_OS_NONCONFORMING1 << 8表示section需要链接标准之外的基于特定操作系统的处理O
SHF_GROUP1 << 9表示section 是section Group的成员,该标志只能为包含在可重定位对象中的section设置G
SHF_TLS1 << 10表示sction包含线程本地存储T
SHF_COMPRESSED1 << 11包含压缩数据,不能与SHF_ALLOC一起使用C

还有一些其他的标志没展现,具体可以看elf.h。

section link && section info

如果段的类型是与连接相关的,那么sh_link、sh_info这两个成员就会有一些意义。

sh_typesh_linksh_info
SHT_DYNAMIC该段所使用的字符串表在段表的下标0
SHT_HASH该段所使用的符号表在段表的下标0
SHT_REL/SHT_RELA该段所使用的符号表在段表的下标重定位表作用的表在段表中的下标
SHT_SYMTAB/SHT_DYNSY操作系统相关操作系统相关
otherSHN_UNDEF0

分析目标文件的section header Table

这边可以使用objdump 或者readelf来观察段表的结构

>> objdump -h main.o 

main.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000048  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  0000000000000000  0000000000000000  00000088  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000008  0000000000000000  0000000000000000  00000090  2**2
                  ALLOC
  3 .rodata       00000009  0000000000000000  0000000000000000  00000090  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .comment      0000001d  0000000000000000  0000000000000000  00000099  2**0
                  CONTENTS, READONLY
  5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000b6  2**0
                  CONTENTS, READONLY
  6 .eh_frame     00000058  0000000000000000  0000000000000000  000000b8  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA


>> readelf -S main.o
There are 13 section headers, starting at offset 0x418:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000048  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  00000338
       0000000000000048  0000000000000018   I      10     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000088
       0000000000000008  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  00000090
       0000000000000008  0000000000000000  WA       0     0     4
  [ 5] .rodata           PROGBITS         0000000000000000  00000090
       0000000000000009  0000000000000000   A       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  00000099
       000000000000001d  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000b6
       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  000000b8
       0000000000000058  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  00000380
       0000000000000030  0000000000000018   I      10     8     8
  [10] .symtab           SYMTAB           0000000000000000  00000110
       0000000000000198  0000000000000018          11    11     8
  [11] .strtab           STRTAB           0000000000000000  000002a8
       000000000000008c  0000000000000000           0     0     1
  [12] .shstrtab         STRTAB           0000000000000000  000003b0
       0000000000000061  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

可以看到readelf 输出的内容会比objdump更多,因为objdump会省略一些辅助性的段。在前文elf header中可以看到main.o中的Number of section headers确实是13,与readelf输出段的个数匹配,不过ELF段表的第一个元素是无效的描述符,所以真正有效的描述符只有12个

nameTypeflag描述
.textPROGBITSSHF_ALLOC && SHF_EXECINSTR代码段,加载时需要分配空间且可以被执行
.rela.textRELASHF_INFO_LINK代码段的重定位段,sh_link字段包含符号表在段表的下标,sh_info可以确定作用于.text
.dataPROGBITSSHF_WRITE && SHF_ALLOC数据段,可写入且加载时需要分配空间
.bssNOBITSSHF_WRITE && SHF_ALLOCBlock Started by Symbol,存储没有初始化或者初始化为0的全局变量,文件中不存在内容,但加载后可写入且需要分配空间
.rodataPROGBITSSHF_ALLOC只读数据段存储常量数据,比如程序中定义为const的全局变量,#define定义的常量。 加载后需要分配空间
.commentPROGBITSSHF_MERGE && SHF_STRINGS注释信息段,在连接的时候可以合并该段,并且段中存储的是以NULL为结尾的字符串
.note.GNU-stackPROGBITS堆栈提示段
.eh_framePROGBITSSHF_ALLOC这个段在GCC生成处理异常的代码时,描述如何展开堆栈 。加载时需要分配空间
.rela.eh_frameRELASHF_INFO_LINK.eh_frame的重定位段,由sh_info可以确定作用于.eh_frame
.symtabSYMTAB符号表
.strtabSTRTAB字符串表
.shstrtabSTRTAB段表字符串表,通常存储段名

重定位表

重定位表表项的结构回在静态连接中总结

字符串表

因为字符串的长度一般都不固定,所以常见的做法是存放到统一的表里
在这里插入图片描述
让偏移和字符串可以一一对应
在这里插入图片描述
这样在ELF文件中只需要引用一个字符串表的偏移就可以了。常见的字符串表就是.strtab(字符串表) 和 .shstrtab(段表字符串表)。字符串表用来保存普通的字符串,比如符号名字等。而段表字符串表用来保存段表中会用到的字符串,比如段表名字等。

回到最开头的mian.o文件中,在ELF Header里由一个e_shstrndx,这个变量是段表字符串表在段表中的下标,即.shstrtab在段表中的下标,可以对比ELF headr的输出和readelf -S 的输出,发现e_shstrndx确实是12。

符号表

.symtab 是由 Elf32_Sym/Elf64_Sym 够成的一个数组,其定义如下:

typedef struct
{
  Elf64_Word    st_name;        // 符号名字在字符串表中的下标
  unsigned char st_info;        //  符号类型和绑定信息
  unsigned char st_other;      // 貌似没用
  Elf64_Section st_shndx;     // 符号所在段,但部分特殊符号意义稍微特殊一点
  Elf64_Addr    st_value;       // 符号值,不同符号这个字段的意义不一致
  Elf64_Xword   st_size;      // 符号大小,如果为0则大小为未知
} Elf64_Sym;

st_info

st_info 的低4位用来代表符号类型,高28位代表符号绑定信息。
绑定信息的部分宏定义如下:

宏定义描述
STB_LOCAL0局部符号,目标文件之外不可见
STB_GLOBAL1全局符号,所有目标文件都可见
STB_WEAK2弱符号,类似于全局符号,但定义具有较低优先级

符号类型的部分宏定义如下

宏定义描述
STT_NOTYPE0未知类型
STT_OBJECT1符号是个数据对象,比如变量、数组等
STT_FUNC2符号是个函数
STT_SECTION3表明该符号是一个段,这个符号必须是STB_LOCA的
STT_FILE4该符号是文件名字,一般是该目标文件对应的源文件名, 一定是STB_LOCAL类型,且st_shndx一定是SHN_ABS
STT_COMMON5该符号是一个未初始化的公共块,处理方式会与 STB_LOCAL 相同

st_shndx

符号如果定义在本文件中,则该字段就是 所在段 在 段表中的下标。如果不是定义在目标文件以及对于有些特殊的符号,则是按以下定义来。

宏定义描述
SHN_UNDEF0符号未定义,这个符号在该目标文件中有引用,但定义不在该目标文件中
SHN_ABS1表示该符号包含一个绝对的值,如文件名称这种符号
SHN_COMMON2表示该符号属于未初始化的公共块,比如mina.o中定义的gloabal_uninit_var这个变量
还有一些特殊定义没展现。

st_value

这个变量对于不同情况有不同的定义:

  • 如果符号在目标文件中,且符号的st_shndx不是SHN_COMMON,则st_value表示符号在段中的偏移,最常见的就是全局变量的符号
  • 如果符号在目标文件中,且符号的st_shndx是SHN_COMMON,则st_value是对齐属性
  • 如果符号在可执行文件中,则st_value表示符号的虚拟地址,这个对于动态连接十分有用。

分析main.o的符号表

>>readelf -s main.o 
Symbol table '.symtab' contains 17 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS main.cpp
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    3 _ZZ4mainE10static_var
     7: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    4 _ZZ4mainE11static_var2
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    8 
    10: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
    11: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_init_var
    12: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 global_uninit_var
    13: 0000000000000000    36 FUNC    GLOBAL DEFAULT    1 _Z5func1i
    14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _Z6printfPKcz
    16: 0000000000000024    36 FUNC    GLOBAL DEFAULT    1 main

>>>objdump -t main.o 
main.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 main.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000004 l     O .data  0000000000000004 _ZZ4mainE10static_var
0000000000000004 l     O .bss   0000000000000004 _ZZ4mainE11static_var2
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 g     O .data  0000000000000004 global_init_var
0000000000000000 g     O .bss   0000000000000004 global_uninit_var
0000000000000000 g     F .text  0000000000000024 _Z5func1i
0000000000000000         *UND*  0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000         *UND*  0000000000000000 _Z6printfPKcz
0000000000000024 g     F .text  0000000000000024 main

符号表的第一项是无效的,所以main.o中16个有效符号,然后Name被readelf直接读取字符串表给翻译出来出来了。

符号下标描述
1该符号是文件名字, 内容是绝对的值,符号名字是main.cpp
6该符号是个数据对象,是个本地符号,定义在该目标文件中,所在段的下标是3,也就是.data段,名字是_ZZ4mainE10static_var,长度是4,在段中的偏移是4
7该符号是个数据对象,是个本地符号,定义在该目标文件中,所在段的下标是4,也就是.bss段,名字是_ZZ4mainE11static_var2, 长度是4,在段中的偏移是4
11该符号是个数据对象,是个全局符号,定义在该目标文件中,所在段的下标是3,也就是.data段,名字是global_init_var, 长度是4, 在段中偏移是0
12该符号是个数据对象,是个全局符号,定义在该目标文件中,所在段的下标是4,也就是.bss段,名字是global_uninit_var, 长度是4, 在段中偏移是0
13该符号是个函数对象,是个全局符号,所在段的下标是1,也就是.textt段,名字是_Z5func1i, 长度是36
14该符号类型未定义,是个全局符号,在该文件中只是引用,名字是_GLOBAL_OFFSET_TABLE_,实际上这个是一个由编译器生成的符号,用于定位全局地址无关的变量的真实地址,素材GOT
15该符号是个未定义,是个全局符号,在该文件中只是引用,名字是_Z6printfPKcz,实际上这个是printf函数,文件中确实对printf没有进行定义
16该符号是个函数对象,是个全局符号,定义在该目标文件中,所在段的下标是1,也就是.text段,函数名字是main,长度36,在段中偏移是0X24

对于其他Type是section的符号,实际上都是对应Ndx的段的段名,readelf没有显示,但objdump 可以看到这些符号的名字。

然后通过objdump 可以查看代码段,对上述处于代码段的符号偏移进行验证

>>> objdump -d main.o 
main.o:     file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <_Z5func1i>:
  ......
  23:   c3                      retq   

0000000000000024 <main>:
  ......
  47:   c3                      retq   

可以看到_Z5func1i从0X00开始长度为36(0X24), 从0x24开始是main函数的内容,长度为36(0x2f)。

然后可以通过hexdump来对数据段的内容进行验证:

>> hexdump -n 8 -s 0x88 main.o
0000088 0054 0000 0005 0000                    
0000090

数据段在文件中偏移为0x88,长度为8, 前4个字节是global_init_var,内容是采用小端序存储,其值为0x00000054,十进制下位84.第4到7个字节为_ZZ4mainE10static_var,内容是0X00000005.

总结

这边较为深入的介绍了ELF Header 、section Header 、以及secton的结构,并使用了《程序员的自我修养-链接、装载与库》这本书上的例子作为实验的内容,详细展现了目标文件中的这些信息应该如何解读。
在知道了目标文件中的结构后,接下来的问题就是如何在链接的时候将他们组合起来,形成一个可执行文件或者是.so文件。

引用

  • 程序员的自我修养-链接、装载与库.pdf
  • https://sp4n9x.github.io/2021/05/27/ELF_FileFormat_Analysis/ ELF文件格式分析
  • https://blog.csdn.net/wyzworld/article/details/114805643 ELF文件详解
  • https://zhuanlan.zhihu.com/p/286088470
  • http://nicephil.blinkenshell.org/my_book/ch04.html
  • https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-79797/index.html

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

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

相关文章

2021年大数据挑战赛B题口罩佩戴检测求解全过程论文及程序

2021年大数据挑战赛 B题 口罩佩戴检测 原题再现&#xff1a; 新冠疫情的爆发对人类生命安全及全球经济发展造成了重大影响。虽然现在国内疫情基本得到有效遏制&#xff0c;但日常防控仍不可松懈。戴口罩是预防新冠肺炎最便捷、最有效的措施和方法。人脸佩戴口罩的自动化识别可…

2022跨境支付回顾,iPayLinks让“链接”更高效

从2015年服务第一个客户开始iPayLinks已陪伴用户走过8个春秋作为贴心的跨境资金管家iPayLinks跨越山海&#xff0c;链接全球以产品为基石这一年&#xff0c;iPayLinks持续开发新产品、新功能&#xff0c;帮助外贸企业和跨境卖家抓住机遇&#xff0c;降本增效。B2B外贸收款主打“…

Python 使用TF-IDF

第一个 简易版本 直接来至 jieba 包&#xff0c; 一下代码直接来源 https://blog.csdn.net/qq_38923076/article/details/81630442 这里记录 进行对比 jieba.analyse.extract_tags(sentence, topK20, withWeightFalse, allowPOS()) sentence&#xff1a;待提取的文本语料 topK…

【阶段三】Python机器学习25篇:机器学习项目实战:LigthGBM算法的核心思想、原理与LightGBM分类模型

本篇的思维导图: LigthGBM算法的核心思想 LigthGBM算法是Boosting算法的新成员,由微软公司开发。它和XGBoost算法一样是对GBDT算法的高效实现,在原理上与GBDT算法和XGBoost算法类似,都采用损失函数的负梯度作为当前决策树的残差近似值,去拟合新的决策树。 …

MATLAB实验五

实验五 A 1、在同一图形窗口绘制。利用plot绘图指令绘图命令。 &#xff08;1&#xff09;在窗口上部绘制正弦信号 x(t)sin(0.5πtπ4),t∈[0,4π]x(t)sin(0.5\pi t\frac \pi 4),t∈[0,4\pi]x(t)sin(0.5πt4π​),t∈[0,4π]。要求曲线为黑色实线。 &#xff08;2&#xff…

QT(7)-初识委托

初识委托1 简介2 QT中的委托类2.1 函数2.1.1 关键函数2.1.2 其他函数3 例子3.1 官方例子3.2 修改官方例子4 设想1 简介 委托是Qt中的一种机制&#xff0c;用于在Qt模型/视图架构中处理特定类型的数据。委托提供了一种方便的方法来定制特定类型的数据的显示和编辑。 委托可以做…

天空卫士参与编写的《数据安全治理实践指南(2.0)》正式发布

2023年1月5日&#xff0c;由中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;、中国通信标准化协会指导&#xff0c;中国通信标准化协会大数据技术标准推进委员会主办&#xff0c;数据安全推进计划承办的第二届数据安全治理峰会在北京召开。本次峰会发布多项…

算法刷题打卡第64天:平衡二叉树

平衡二叉树 难度&#xff1a;简单 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1&#xff1a; 输入&#xff1a;root [3,9,…

错误票据(第四届蓝桥杯省赛C++A/B组,第四届蓝桥杯省赛JAVAA/B组)

题目详细&#xff1a;解题思路&#xff1a;这题的难点主要在于对于数据的读入以及对于两个数字的查找对于数据的读入&#xff1a;1.直接对单行字符串进行转换&#xff1a;题目所给出的输入只有行数并不知道一行有多少个数字所以我们采用一下读取一行然后对一行的结果进行读入首…

docker提交腾讯云标准模式

简介我们公司的容器化标准模式&#xff0c;本次是以redis为例进行示范技术要求:你会简单的docker容器打包环境需要:docker、docker-compose、联网环境、腾讯云容器及镜像服务&#xff08;公司已有TKE&#xff09;文件需要&#xff1a;除了你自己的Dockerfile所需要的东西外&…

TensorFlow 基础(三)梯度和自动微分

文章目录Computing gradientsGradient tapesGradients with respect to a modelControlling what the tape watchesIntermediate resultsGradients of non-scalar targetsCases where gradients returns NoneReferencesimport numpy as np import matplotlib.pyplot as pltimpo…

【自学Python】Python三目运算符

Python三目运算符 Python三目运算符教程 Python 中没有其他语言类型的三目运算符&#xff0c;但是我们可以借助 if 语句实现类似的三目运算符。 Python三目运算符详解 说明 Python 的三目运算符是借助于 if 语句来实现的。 语法 True_statements if condition else Fals…

千锋教育嵌入式物联网教程之系统编程篇学习-02

目录 系统调用函数与库函数 库函数的组成 库函数与系统调用的关系 进程概述 进程的定义 进程与程序的区别 进程的状态及其转换 进程的调度机制 进程控制块 查看当前系统所有进程 进程号函数 进程创建fork函数 进程挂起 进程的等待 wait() waitpid 特殊进程 …

CPU 运行时的硬件环境详解

注&#xff1a;本文参考小林coding相关文章&#xff0c;侵权请联系 目录 1.图灵机的工作方式 2.冯诺依曼模型 3.内存 4.中央处理器 5总线 6.输入、输出设备 7.线路位宽与 CPU 位宽 代码写了那么多&#xff0c;你知道 a 1 2 这条代码是怎么被 CPU 执行的吗&#xff1f; …

TCP/IP协议族之TCP、UDP协议详解(小白也能看懂)

前言 在进行网络编程之前&#xff0c;我们必须要对网络通信的基础知识有个大概的框架&#xff0c;TCP/IP协议族涉及到多种网络协议&#xff0c;一般说TCP/IP协议&#xff0c;它不是指某一个具体的网络协议&#xff0c;而是一个协议族。本篇章主要针对IP协议、TCP和UDP协议记录总…

常用的代码命名方法

常见的三种命名方法1 驼峰命名法&#xff08;CamelCase&#xff09;驼峰命名法应该我们最常见的一个&#xff0c;这种命名方式使用大小写混合的格式来区别各个单词&#xff0c;并且单词之间不使用空格隔开或者连接字符连接的命名方式1 大驼峰命名法&#xff08;UpperCamelCase&…

Mysql 基础-持续更新

去重 DISTINCT DISTINCT 关键字的主要作用就是对数据表中一个或多个字段重复的数据进行过滤&#xff0c;只返回其中的一条数据给用户 注意点&#xff1a; DISTINCT 关键字只能在 SELECT 语句中使用。在对一个或多个字段去重时&#xff0c;DISTINCT 关键字必须在所有字段的最前…

IPv6路由协议实验配置(ospfv3、isis-ipv6、bgp4+)

目录 OSPFv3实验配置 建立OSPFv3邻居 AR1修改DR优先级 AR1引入直连路由 配置Stub区域 ISIS IPv6实验配置 建立ISIS邻居 修改AR1的DIS优先级 在AR1上配置路由泄露 BGP4实验配置 AR1与AR2、AR3建立IBGP邻居关系 AR2与AR4建立EBGP邻居关系 配置AR1为反射器 OSPFv3实验…

Android时间与服务器同步方案

转自&#xff1a; https://blog.csdn.net/qinci/article/details/70666631这个的吧&#xff1f;转发请注明来源吧&#xff1f;Android时间与服务器同步方法_飛舞的青春的博客-CSDN博客Android时间与服务器同步方案 在部分软件应用场景里&#xff0c;我们对应用时间要求非常苛刻…

mysql navicat函数_Navicat for MySQL函数高级属性

过程和函数是一组可以保存在服务器上的SQL语句。MySQL(www.formysql.com)函数高级属性主要涉及安全性&#xff0c;定义者&#xff0c;数据访问&#xff0c;决定性等方面的内容Navicat 函数高级属性安全性&#xff1a;指定用创建函数的用户权限来运行函数&#xff0c;或是用启用…