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

编译链接实战(8)认识elf文件格式

🎀 关于博主👇🏻👇🏻👇🏻

🥇 作者简介: 热衷于知识探索和分享的技术博主。
💂 csdn主页::【奇妙之二进制】
✍️ 微信公众号:【Linux 世界】

🎉精彩专栏:

🎓 【面向工作git基础教程】
​ 🧡 【C++11新特性深入剖析】
​ 📚【shell脚本编程基础与实战】
​ 🌎【Linux网络编程面试演练】
✍️ 【C++编译工具cmake入门到精通】
​ …

💂关于作者: 曾就职于国内知名安防上市公司,现就职于国内知名AMR机器人公司,担任高级系统软件工程师。2020年至今保持CSDN博客专家,CSDN C/C++领域优质创作者头衔。全网5万+粉丝。十载寒冰,难凉热血;多年过去,历经变迁,物是人非。 然而,对于技术的探索和追求从未停歇。 💪坚持创作,热衷分享,初心未改,继往开来!

文章目录

    • 🎀 关于博主👇🏻👇🏻👇🏻
      • 1、ELF文件简介
        • 可重定位的对象文件(Relocatable file)
        • 可执行的对象文件(Executable file)
        • 可被共享的对象文件(Shared object file)
      • 2、ELF文件格式
      • 3、分析ELF文件头
      • 4、节头表Section Header Table
      • 5、程序头表Program Header Table
      • 总结

1、ELF文件简介

首先,你需要知道的是所谓对象文件(Object files)有三个种类:

可重定位的对象文件(Relocatable file)

这是由汇编器汇编生成的 .o 文件。后面的链接器(link editor)拿一个或一些 Relocatable object files 作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file)。我们可以使用 ar 工具将众多的 .o Relocatable object files 归档(archive)成 .a 静态库文件。另外,可以预先告诉大家的是我们的内核可加载模块 .ko 文件也是 Relocatable object file。

可执行的对象文件(Executable file)

这我们见的多了。文本编辑器vi、调式用的工具gdb、播放mp3歌曲的软件mplayer等等都是Executable object file。你应该已经知道,在我们的 Linux 系统里面,存在两种可执行的东西。除了这里说的 Executable object file,另外一种就是可执行的脚本(如shell脚本)。注意这些脚本不是 Executable object file,它们只是文本文件,但是执行这些脚本所用的解释器就是 Executable object file,比如 bash shell 程序。

可被共享的对象文件(Shared object file)

这些就是所谓的动态库文件,也即 .so 文件。如果拿前面的静态库来生成可执行程序,那每个生成的可执行程序中都会有一份库代码的拷贝。如果在磁盘中存储这些可执行程序,那就会占用额外的磁盘空间;另外如果拿它们放到Linux系统上一起运行,也会浪费掉宝贵的物理内存。如果将静态库换成动态库,那么这些问题都不会出现。动态库在发挥作用的过程中,必须经过两个步骤:

a) 链接编辑器(link editor)拿它和其他Relocatable object file以及其他shared object file作为输入,经链接处理后,生成另外的 shared object file 或者 executable file。

b)在运行时,动态链接器(dynamic linker)拿它和一个Executable file以及另外一些 Shared object file 来一起处理,在Linux系统里面创建一个进程映像。

2、ELF文件格式

首先,ELF文件格式提供了两种视图,分别是链接视图和执行视图。

合并成一张图:

链接视图是以节(section)为单位,执行视图是以段(segment)为单位。链接视图就是在链接时用到的视图,而执行视图则是在执行时用到的视图。上图左侧的视角是从链接来看的,右侧的视角是执行来看的。整个文件可以分为四个部分:

  • ELF header:elf文件头部信息,描述整个文件的组织。
  • Program Header Table: 描述文件中的各种segments, 每个segment都用一个表项来描述,表项记录了该segment在文件中的起始地址,以及大小等信息。这些表项(entry)就构成了程序头表。你可以理解成一个结构体数组。用来告诉系统如何创建进程映像。
  • sections 或者 segments:segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,也就是说,在链接阶段,我们可以忽略program header table来处理此文件,在运行阶段可以忽略section header table来处理此程序(所以很多加固手段删除了section header table)。从图中我们也可以看出,segments与sections是包含的关系,一个segment包含若干个section。
  • Section Header Table: 每个section都用一个表项来描述,表项记录了该section在文件中的起始地址,以及大小等信息。这些表项(entry)就构成了节头表。你可以理解成一个结构体数组。

备注:下面开始section翻译成节,segment翻译成段。

3、分析ELF文件头

vi /usr/include/elf.h查看elf头数据结构:

/* The ELF file header.  This appears at the start of every ELF file.  */#define EI_NIDENT (16)typedef struct
{unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */Elf32_Half	e_type;			/* Object file type */Elf32_Half	e_machine;		/* Architecture */Elf32_Word	e_version;		/* Object file version */Elf32_Addr	e_entry;		/* Entry point virtual address */Elf32_Off	e_phoff;		/* Program header table file offset */Elf32_Off	e_shoff;		/* Section header table file offset */Elf32_Word	e_flags;		/* Processor-specific flags */Elf32_Half	e_ehsize;		/* ELF header size in bytes */Elf32_Half	e_phentsize;		/* Program header table entry size */Elf32_Half	e_phnum;		/* Program header table entry count */Elf32_Half	e_shentsize;		/* Section header table entry size */Elf32_Half	e_shnum;		/* Section header table entry count */Elf32_Half	e_shstrndx;		/* Section header string table index */
} Elf32_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 -h查看程序elf头:

root@AI-Machine:/home/hongjh/2019_project# readelf -h a.out  
ELF Header:Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class:                             ELF32Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              EXEC (Executable file)Machine:                           Intel 80386Version:                           0x1Entry point address:               0x8048340Start of program headers:          52 (bytes into file)Start of section headers:          6144 (bytes into file)Flags:                             0x0Size of this header:               52 (bytes)Size of program headers:           32 (bytes)Number of program headers:         9Size of section headers:           40 (bytes)Number of section headers:         31Section header string table index: 28

上面指示了节头表、程序头表在文件的偏移,有多少表项,每个表项的大小,程序的运行平台,大小端,文件类型(可执行文件EXEC、可重定位文件REL、共享目标文件DYN),是32位还是64位。

Entry point address表示该程序在内存的入口地址,即加载地址。

Machine指示了该文件的平台。

ELF header的定义可以在 /usr/include/elf.h 中找到。Elf32_Ehdr是32位 ELF header的结构体。Elf64_Ehdr是64位ELF header的结构体。

/* Section header.  */typedef struct
{Elf32_Word	sh_name;		/* Section name (string tbl index) */Elf32_Word	sh_type;		/* Section type */Elf32_Word	sh_flags;		/* Section flags */Elf32_Addr	sh_addr;		/* Section virtual addr at execution */Elf32_Off	sh_offset;		/* Section file offset */Elf32_Word	sh_size;		/* Section size in bytes */Elf32_Word	sh_link;		/* Link to another section */Elf32_Word	sh_info;		/* Additional section information */Elf32_Word	sh_addralign;		/* Section alignment */Elf32_Word	sh_entsize;		/* Entry size if section holds table */
} Elf32_Shdr;typedef struct
{Elf64_Word	sh_name;		/* Section name (string tbl index) */Elf64_Word	sh_type;		/* Section type */Elf64_Xword	sh_flags;		/* Section flags */Elf64_Addr	sh_addr;		/* Section virtual addr at execution */Elf64_Off	sh_offset;		/* Section file offset */Elf64_Xword	sh_size;		/* Section size in bytes */Elf64_Word	sh_link;		/* Link to another section */Elf64_Word	sh_info;		/* Additional section information */Elf64_Xword	sh_addralign;		/* Section alignment */Elf64_Xword	sh_entsize;		/* Entry size if section holds table */
} Elf64_Shdr;

4、节头表Section Header Table

上面提到节头表就是一个结构体数组,该结构体定义如下:

typedef struct
{Elf64_Word    sh_name;                /* Section name (string tbl index) */Elf64_Word    sh_type;                /* Section type */Elf64_Xword   sh_flags;               /* Section flags */Elf64_Addr    sh_addr;                /* Section virtual addr at execution */Elf64_Off     sh_offset;              /* Section file offset */Elf64_Xword   sh_size;                /* Section size in bytes */Elf64_Word    sh_link;                /* Link to another section */Elf64_Word    sh_info;                /* Additional section information */Elf64_Xword   sh_addralign;           /* Section alignment */Elf64_Xword   sh_entsize;             /* Entry size if section holds table */
} Elf64_Shdr;

一个ELF文件中到底有哪些具体的section,由包含在这个ELF文件的section head table(SHT)决定。在SHT中,针对每一个section,都设置一个条目,用来描述对应的这个section,其内容主要包括该section的名称、类型、大小以及在整个ELF文件中的字节偏移位置等等。

使用readelf -S a.out读取节头表:

root@AI-Machine:/home/hongjh/2019_project# readelf -S a.out  
There are 31 section headers, starting at offset 0x1800:Section Headers:[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al[ 0]                   NULL            00000000 000000 000000 00      0   0  0[ 1] .interp           PROGBITS        08048154 000154 000013 00   A  0   0  1[ 2] .note.ABI-tag     NOTE            08048168 000168 000020 00   A  0   0  4[ 3] .note.gnu.build-i NOTE            08048188 000188 000024 00   A  0   0  4[ 4] .gnu.hash         GNU_HASH        080481ac 0001ac 000020 04   A  5   0  4[ 5] .dynsym           DYNSYM          080481cc 0001cc 000060 10   A  6   1  4[ 6] .dynstr           STRTAB          0804822c 00022c 000052 00   A  0   0  1[ 7] .gnu.version      VERSYM          0804827e 00027e 00000c 02   A  5   0  2[ 8] .gnu.version_r    VERNEED         0804828c 00028c 000020 00   A  6   1  4[ 9] .rel.dyn          REL             080482ac 0002ac 000008 08   A  5   0  4[10] .rel.plt          REL             080482b4 0002b4 000018 08  AI  5  24  4[11] .init             PROGBITS        080482cc 0002cc 000023 00  AX  0   0  4[12] .plt              PROGBITS        080482f0 0002f0 000040 04  AX  0   0 16[13] .plt.got          PROGBITS        08048330 000330 000008 00  AX  0   0  8[14] .text             PROGBITS        08048340 000340 0001a2 00  AX  0   0 16[15] .fini             PROGBITS        080484e4 0004e4 000014 00  AX  0   0  4[16] .rodata           PROGBITS        080484f8 0004f8 000008 00   A  0   0  4[17] .eh_frame_hdr     PROGBITS        08048500 000500 00002c 00   A  0   0  4[18] .eh_frame         PROGBITS        0804852c 00052c 0000cc 00   A  0   0  4[19] .init_array       INIT_ARRAY      08049f08 000f08 000004 00  WA  0   0  4[20] .fini_array       FINI_ARRAY      08049f0c 000f0c 000004 00  WA  0   0  4[21] .jcr              PROGBITS        08049f10 000f10 000004 00  WA  0   0  4[22] .dynamic          DYNAMIC         08049f14 000f14 0000e8 08  WA  6   0  4[23] .got              PROGBITS        08049ffc 000ffc 000004 04  WA  0   0  4[24] .got.plt          PROGBITS        0804a000 001000 000018 04  WA  0   0  4[25] .data             PROGBITS        0804a018 001018 000008 00  WA  0   0  4[26] .bss              NOBITS          0804a020 001020 000004 00  WA  0   0  1[27] .comment          PROGBITS        00000000 001020 000035 01  MS  0   0  1[28] .shstrtab         STRTAB          00000000 0016f6 00010a 00      0   0  1[29] .symtab           SYMTAB          00000000 001058 000460 10     30  47  4[30] .strtab           STRTAB          00000000 0014b8 00023e 00      0   0  1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings)I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)O (extra OS processing required) o (OS specific), p (processor specific)

该程序一共有31个节,第0个节通常是个空节。这里有我们熟悉的:

  [14] .text             PROGBITS        08048340 000340 0001a2 00  AX  0   0 16[16] .rodata           PROGBITS        080484f8 0004f8 000008 00   A  0   0  4[25] .data             PROGBITS        0804a018 001018 000008 00  WA  0   0  4[26] .bss              NOBITS          0804a020 001020 000004 00  WA  0   0  1
  1. .text section 里装载了可执行代码;

  2. .data section 里面装载了被初始化的数据;

  3. .bss section 里面装载了未被初始化的数据;

  4. 以 .rec 打头的 sections 里面装载了重定位条目;

  5. .symtab 或者 .dynsym section 里面装载了符号信息;

  6. .strtab 或者 .dynstr section 里面装载了字符串信息;

  7. 其他还有为满足不同目的所设置的section,比方满足调试的目的、满足动态链接与加载的目的等等。

关于这些section的细节,后面再深入。

5、程序头表Program Header Table

程序头部(Program Header)描述与程序执行直接相关的目标文件结构信息。用来定位各个段(segment)的映像。同时包含其他一些用来为程序创建映像所必须的信息。

可执行文件或者可被共享的对象文件才有segment,所以才有程序头表,表中的每一项描述了一个segment的信息。目标文件的segment包含一个或者多个section,也就是“段内容(Segment Contents)”。

section 是被链接器使用的,但是 segments 是被加载器所使用的。加载器会将所需要的 segment 加载到内存空间中运行。

对于可重定位的对象文件(例如.o文件)不包含程序头表(因为它不需要被加载器加载运行)。

程序头部的数据结构如下:

typedef struct {  Elf32_Word p_type;           //此数组元素描述的段的类型,或者如何解释此数组元素的信息。 Elf32_Off  p_offset;           //此成员给出从文件头到该段第一个字节的偏移Elf32_Addr p_vaddr;         //此成员给出段的第一个字节将被放到内存中的虚拟地址Elf32_Addr p_paddr;        //此成员仅用于与物理地址相关的系统中。System V忽略所有应用程序的物理地址信息。Elf32_Word p_filesz;         //此成员给出段在文件映像中所占的字节数。可以为0。Elf32_Word p_memsz;     //此成员给出段在内存映像中占用的字节数。可以为0。Elf32_Word p_flags;         //此成员给出与段相关的标志。Elf32_Word p_align;        //此成员给出段在文件中和内存中如何对齐。
} Elf32_phdr;

p_type指示了程序头的类型,类型定义如下:

/* Special value for e_phnum.  This indicates that the real number ofprogram headers is too large to fit into e_phnum.  Instead the realvalue is in the field sh_info of section 0.  */#define PN_XNUM         0xffff/* Legal values for p_type (segment type).  */#define PT_NULL         0               /* Program header table entry unused */
#define PT_LOAD         1               /* Loadable program segment */
#define PT_DYNAMIC      2               /* Dynamic linking information */
#define PT_INTERP       3               /* Program interpreter */
#define PT_NOTE         4               /* Auxiliary information */
#define PT_SHLIB        5               /* Reserved */
#define PT_PHDR         6               /* Entry for header table itself */
#define PT_TLS          7               /* Thread-local storage segment */
#define PT_NUM          8               /* Number of defined types */
#define PT_LOOS         0x60000000      /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550      /* GCC .eh_frame_hdr segment */
#define PT_GNU_STACK    0x6474e551      /* Indicates stack executability */
#define PT_GNU_RELRO    0x6474e552      /* Read-only after relocation */
#define PT_LOSUNW       0x6ffffffa
#define PT_SUNWBSS      0x6ffffffa      /* Sun Specific segment */
#define PT_SUNWSTACK    0x6ffffffb      /* Stack segment */
#define PT_HISUNW       0x6fffffff
#define PT_HIOS         0x6fffffff      /* End of OS-specific */
#define PT_LOPROC       0x70000000      /* Start of processor-specific */
#define PT_HIPROC       0x7fffffff      /* End of processor-specific */

可以通过readelf -l a.out查看程序头表:

root@AI-Machine:/home/hongjh/2019_project# readelf -l a.out    Elf file type is EXEC (Executable file)
Entry point 0x102b4
There are 9 program headers, starting at offset 52Program Headers:Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg AlignEXIDX          0x000474 0x00010474 0x00010474 0x00008 0x00008 R   0x4PHDR           0x000034 0x00010034 0x00010034 0x00120 0x00120 R E 0x4INTERP         0x000154 0x00010154 0x00010154 0x00013 0x00013 R   0x1[Requesting program interpreter: /lib/ld-linux.so.3]LOAD           0x000000 0x00010000 0x00010000 0x00480 0x00480 R E 0x10000LOAD           0x000f0c 0x00020f0c 0x00020f0c 0x00118 0x0011c RW  0x10000DYNAMIC        0x000f18 0x00020f18 0x00020f18 0x000e8 0x000e8 RW  0x4NOTE           0x000168 0x00010168 0x00010168 0x00020 0x00020 R   0x4GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10GNU_RELRO      0x000f0c 0x00020f0c 0x00020f0c 0x000f4 0x000f4 R   0x1Section to Segment mapping:Segment Sections...00     .ARM.exidx 01     02     .interp 03     .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .ARM.exidx .eh_frame 04     .init_array .fini_array .jcr .dynamic .got .data .bss 05     .dynamic 06     .note.ABI-tag 07     08     .init_array .fini_array .jcr .dynamic 

这验证了第一张图中所述,segment是section的一个集合,sections按照一定规则映射到segment。那么为什么需要区分两种不同视图?

当ELF文件被加载到内存中后,系统会将多个具有相同权限(flg值)section合并一个segment。操作系统往往以页为基本单位来管理内存分配,一般页的大小为4096B,即4KB的大小。同时,内存的权限管理的粒度也是以页为单位,页内的内存是具有同样的权限等属性,并且操作系统对内存的管理往往追求高效和高利用率这样的目标。ELF文件在被映射时,是以系统的页长度为单位的,那么每个section在映射时的长度都是系统页长度的整数倍,如果section的长度不是其整数倍,则导致多余部分也将占用一个页。而我们从上面的例子中知道,一个ELF文件具有很多的section,那么会导致内存浪费严重。这样可以减少页面内部的碎片,节省了空间,显著提高内存利用率。

总结

链接器在链接可执行文件或动态库的过程中,它会把来自不同可重定位对象文件中的相同名称的section合并起来构成同名的section。接着,它又会把带着相同属性(比方都是只读并可加载的)的section都合并成所谓segment(段)。Segment作为链接器的输出,常被称为输出section。开发者可以控制哪些不同.o文件的section来最后合并构成不同名称的segment。

一个单独的 segment 通常会包含几个不同的 sections,比方一个可被加载的、只读的segment 通常就会包括可执行代码section .text、只读的数据section .rodata以及给动态链接器使用的符号section .dymsym等等。section 是被链接器使用的,但是 segments 是被加载器所使用的。加载器会将所需要的 segment 加载到内存空间中运行。和用 sections header table 来指定一个可重定位文件中到底有哪些 sections 一样。在一个可执行文件或者动态库中,也需要有一种信息结构来指出包含有哪些 segments。这种信息结构就是 program header table,如ELF对象文件格式中右边的 execute view 所示的那样。

相关文章:

编译链接实战(8)认识elf文件格式

🎀 关于博主👇🏻👇🏻👇🏻 🥇 作者简介: 热衷于知识探索和分享的技术博主。 💂 csdn主页::【奇妙之二进制】 ✍️ 微信公众号:【Linux …...

新手小白如何入门黑客技术?

你是否对黑客技术感兴趣呢?感觉成为黑客是一件很酷的事。那么作为新手小白,我们该如何入门黑客技术,黑客技术又是学什么呢? 其实不管你想在哪个新的领域里有所收获,你需要考虑以下几个问题: 首先&#xff…...

【java】Spring Boot --深入SpringBoot注解原理及使用

步骤一 首先,先看SpringBoot的主配置类: SpringBootApplication public class StartEurekaApplication {public static void main(String[] args){SpringApplication.run(StartEurekaApplication.class, args);} }步骤二 点进SpringBootApplication来…...

一文掌握如何对项目进行诊断?【步骤方法和工具】

作为项目经理和PMO,面对错综复杂的项目,需要对组织的项目运作情况进行精确的分析和诊断,找出组织项目管理中和项目运行中存在的问题和潜在隐患,分析其原因,预防风险,并且形成科学合理的决策建议和解决方案&…...

系统分析师真题2020试卷相关概念二

结构化设计相关内容: 结构化设计是一种面向数据流的系统设计方法,它以数据流图和数据字典等文档为基础。数据流图从数据传递和加工的角度,以图形化方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工具及用于表示软件模…...

<<Java开发环境配置>>5-MySQL安装教程(绿色版)

一.MySQL绿色版安装: 1.直接解压下载的ZIP文件到对应的目录下(切记安装目录不要有中文); 如图:我的安装目录:D:Program Files 2.创建配置文件: 在MySQL安装目录下,创建一个my.ini配置文件,然后在里面添加以下内容(别忘了MySQL安装目录要改成…...

空间复杂度与时间复杂度

1、时间复杂度和空间复杂度 (1)时间复杂度、空间复杂度是什么? 算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,空间效率被称作空间复杂度时间复杂度主要衡量的是一…...

javaEE 初阶 — 延迟应答与捎带应答

文章目录1. 延迟应答2. 捎带应答TCP 工作机制:确认应答机制 超时重传机制 连接管理机制 滑动窗口 流量控制与拥塞控制 1. 延迟应答 延时应答 也是提升效率的机制,也是在滑动窗口基础上搞点事情。 滑动窗口的关键是让窗口大小大一点,传输…...

Twitter账号老被封?一文教会你怎么养号

昨天龙哥给大家科普完要怎么批量注册Twitter账号,立刻有朋友来私信龙哥说里面提到的这个养号和防关联具体是个怎么样的做法。由于Twitter检测机制还是比较敏感的,账号很容易被冻结,所以养号是非常重要的步骤。其实要养好Twitter账号其实并不难…...

当遇到国外客户的问题,你解决不了的时候怎么办

对我来说,今年的这个春节假期有点长,差不多休了一个月。复工之后,截止目前做到了60万RMB的业绩,但是相较于往年,整体状态还是差了些。往年的春节,我都是随时待命的状态,整个春节天天坐于电脑前&…...

算法刷题打卡第93天: 最大的以 1 为边界的正方形

最大的以 1 为边界的正方形 难度:中等 给你一个由若干 0 和 1 组成的二维网格 grid,请你找出边界全部由 1 组成的最大 正方形 子网格,并返回该子网格中的元素数量。如果不存在,则返回 0。 示例 1: 输入&#xff1a…...

python语言基础(最详细版)

文章目录一、程序的格式框架缩进1、定义2、这里就简单的举几个例子注释二、语法元素的名称三、数据类型四、数值运算符五、关系运算六、逻辑运算七、运算符的结合性八、字符串一、程序的格式框架 缩进 1、定义 (1)python中通常用缩进来表示代码包含和…...

Java小技能:字符串

文章目录 引言I 预备知识1.1 Object类1.2 重写的规则1.3 hashCode方法II String2.1 String的特性2.2 字符串和正则2.3 StringBuilder,StringBuffer引言 String,StringBuffer,StringBuilder,char[],用来表示字符串。 ​ I 预备知识 1.1 Object类 是所有类的根类 toString…...

2023美赛D题:可持续发展目标

以下内容全部来自人工翻译,仅供参考。 文章目录背景要求术语表文献服务背景 联合国制定了17个可持续发展目标(SDGs)。实现这些目标最终将改善世界上许多人的生活。这些目标并不相互独立,因此,一些目标的积极进展常常…...

openwrt开发板与ubuntu nfs挂载

1.ubuntu需要安装nfs服务 sudo apt-get install nfs-common nfs-kernel-server2.修改 /etc/exports文件: /home/test *(rw,nohide,insecure,no_subtree_check,async,no_root_squash) 前面是挂载的目录,后边是相应权限 rw:读写 insecure&am…...

【Redis】Redis持久化之AOF详解(Redis专栏启动)

📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建工设优化。文章内容兼具广度深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公…...

Git小乌龟每次推送拉取都弹窗和用户名密码报错(解决办法)

目录 一、小乌龟推送代码到云端用户名和密码报错 (一) 遇到问题 (二)解决办法 二、小乌龟每次推送拉取都要输入账号和密码 (一)遇到问题 (二)解决办法 一、小乌龟推送代码到云…...

emacs 使用集锦

emacs 使用集锦 声明, 主要在c/c环境中使用! ---------------------------------------- 1. emacs 中 TAGS 位置设置 ---------------------------------------- a)临时使用方式: M-x visit-tags-table b)启动Emacs时自动加载方式&#xff…...

蓝牙 - 如何实现安全性

蓝牙技术在加密上做了很多工作,来保证你的数据安全。 这些年来,我们的许多电子设备都转向了使用无线技术进行连接。我们的鼠标、键盘、耳机和扬声器上不再有长长的纠缠的电线,而使用了简单方便的无线技术,科技进步改善了我们的生活…...

深入理解顺序io和随机io(全网最详细篇)

MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql的索引分类&a…...

面试准备知识点与总结——(基础篇)

目录Java基础Java面向对象有哪些特征ArrayList和LinkedList有什么区别高并发的集合有哪些问题迭代器的fail-fast和fail-safeArrayList底层扩容机制HashMap面试合集解答设计模式单例设计模式哪些地方体现了单例模式Java基础 Java面向对象有哪些特征 Java面向对象有三大特征&am…...

Linux共享库,静态库与相关系统调用,工具的使用总结

tags: Linux C Syscall 写在前面 总结Unix/Linux操作系统的共享库/静态库部分, 以及一些系统调用. 参考Linux/UNIX系统编程手册41-42章. 测试程序均在Ubuntu下使用cc(gcc-9)运行成功. $ gcc -v Using built-in specs. COLLECT_GCCgcc COLLECT_LTO_WRAPPER/usr/lib/gcc/x86_64…...

「JVM 编译优化」javac 编译器源码解读

Java 的编译过程 前端编译: 编译器的前端,将 Java 文件转变成 Class 文件的过程;如 JDK 的 javac、Eclipse JDT 中的增量式编译器 ECJ;即使编译: JIT,Just In Time Compiler,在运行期将字节码转变成本地机器码的过程&…...

Leetcode DAY 34: K次取反后最大化的数组和 and 加油站 and 分发糖果

1005.K次取反后最大化的数组和 class Solution:def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:nums sorted(nums, key abs, reverse True)for i in range(len(nums)):if nums[i] < 0:nums[i] -nums[i]k - 1else:continueif k 0:return sum(…...

2023美赛A题思路

在线解析 https://kdocs.cn/l/ccNGjN9sGugL​kdocs.cn/l/ccNGjN9sGugL A题思路&#xff1a;&#xff08;具体以题目解决问题顺序为主&#xff09; 这道题分析植被就行&#xff0c;主要涉及不同植被间的相互作用&#xff0c;有竞争有相互促进&#xff0c;我查了下“植物科学数…...

前端上传文件

前言 以 vue 举例&#xff0c;原生 html css js 现在应该很少有人去写了 一、绘制样式 绘制两个标签&#xff0c;一个 <div></div> &#xff0c;一个 <input type"file" />&#xff1b; 为 <div></div>添加 css 样式&#xff0c…...

后台管理系统中选项卡的动态渲染

动态渲染选项卡其中router-link是为了当点击选项卡时跳转到选项卡所在的列表选项卡需要动态渲染&#xff0c;其中active是当选中后激活选中的样式为图标添加点击删除事件在状态机配置tabMenu&#xff08;为了动态渲染&#xff09;需要在tabMenu添加&#xff1a;active、title、…...

网络层重点协议之IP协议(IPv4)

网络层的作用就是来路由的选择&#xff0c;规划传输的路径&#xff0c;其中网络层的重点协议就是IP协议。4位版本号版本号的取值只有4和64位首部长度描述了IP报头有多长&#xff0c;报头中有一个选项部分&#xff0c;是变长的&#xff0c;是可有可无的部分&#xff0c;所以IP报…...

CentOS Stream 8配置DNS

1&#xff1a;用CentOS搭建DNS的目的是想解析一台下载服务器&#xff0c;IP地址172.18.0.58&#xff0c;现在是用IP地址方的式访问&#xff0c;想搭建DNS服务器用域名的方式访问。 使用下面的命令查看一下当前系统的Bind版本。 yum info bind 版本是9.11.36.我的CentOS是最小…...

【roLabelImg】windows下旋转框标注软件安装、使用、rolabelimg打包成exe

主要参考&#xff1a; roLabelImg安装、使用、数据格式roLabelImg在Win10系统下打包成exe - 问雪的文章 - 知乎 一、安装 1.1 直接下载exe运行 劝大家直接去下别人编译好的吧&#xff0c;本来是训练模型标记的&#xff0c;结果搞了半天去了解这个软件了&#xff0c;哎~ 我…...

网站怎么做登陆/应用商店app下载

如果您使用的是 Ubuntu Linux 系统并且想要共享主目录中的公共&#xff08;或任意其他的&#xff09;文件夹&#xff0c;只需右键单击你想要分享的文件夹并选择本地网络共享&#xff0c;如下所示&#xff1a; 在文件夹共享设置窗格中&#xff0c;选中“共享此文件夹”框以与他人…...

网站建设公司创业/宣传渠道有哪些

分享给大家一篇文章&#xff0c;教你怎样用Python画了一棵圣诞树&#xff0c;快来学习。如何用Python画一个圣诞树呢&#xff1f;最简单&#xff1a;height 5​stars 1for i in range(height):print(( * (height - i)) (* * stars))stars 2print(( * height) |)效果&…...

连接国外网站做端口映射/学seo建网站

1.Linux严格区分大小写&#xff0c;以点开头的文件是隐藏文件&#xff0c;比如说.abc。 2.Linux的文件类型&#xff1a;Linux的文件是以存储的类型来区别的&#xff0c;与后缀名无关。 (1)普通文件&#xff0c; -,f (2)目录文件&#xff0c; d (3)链接文件&#xff0c; 符号链接…...

做美食网站的目的/网络销售渠道有哪些

通用源码&#xff1a;飞狐软件&#xff0c;大智慧&#xff0c;通达信测试过&#xff0c;通过VAR1:IF(DATE<1990601 AND DATE>931208,1,0);RSV:(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100;K:SMA(RSV,3,1);D:SMA(K,3,1);J:3*K-2*D;金浪:(KDJ)/3,COLORYELLOW;平均:MA…...

wordpress短码/直播营销策略有哪些

先画个图,便于理解 POJO &#xff1a;plain ordinary java object 无规则简单java对象 一个中间对象&#xff0c;可以转化为PO、DTO、VO。 1 &#xff0e;POJO持久化之后〉PO(persistent object持久对象) 2 &#xff0e;POJO传输过程中〉DTO 3 &#xff0e;POJO用作表示层〉VO …...

做博客网站要什么技术/泰州seo

版权声明&#xff1a;本文为CSDN博主「sac761」的原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接及本声明。 原文链接&#xff1a;https://blog.csdn.net/sac761/article/details/47054977 FreeRTOS是一个迷你的实时操作系统内核。FreeRT…...