ELF文件格式的详解

2023-11-03

  • 1.说明

  • 2.elf文件的基本格式

  • 3.elf文件的头部信息

  • 4.elf文件的节区(Section)

    • 4.1 节区的作用

    • 4.2 节区的组成

  • 5.elf文件的段(Segment)

  • 6.用python解析elf文件

  • 7.总结

1.说明

ELF的英文全称是The Executable and Linking Format,最初是由UNIX系统实验室开发、发布的ABI(Application Binary Interface)接口的一部分,也是Linux的主要可执行文件格式。

从使用上来说,主要的ELF文件的种类主要有三类:

  • 可执行文件(.out):Executable File,包含代码和数据,是可以直接运行的程序。其代码和数据都有固定的地址 (或相对于基地址的偏移 ),系统可根据这些地址信息把程序加载到内存执行。

  • 可重定位文件(.o文件):Relocatable File,包含基础代码和数据,但它的代码及数据都没有指定绝对地址,因此它适合于与其他目标文件链接来创建可执行文件或者共享目标文件。

  • 共享目标文件(.so):Shared Object File,也称动态库文件,包含了代码和数据,这些数据是在链接时被链接器(ld)和运行时动态链接器(ld.so.l、libc.so.l、ld-linux.so.l)使用的。

本文主要从elf文件的组成构造的角度来进行分析,将elf文件的解析通过一步一步的分析得到里面的信息,同时通过python脚本解析,可以直观的看到文件的信息,通过本文的阅读,将对elf文件格式有着更加深刻的理解。

2.elf文件的基本格式

elf文件是有一定的格式的,从文件的格式上来说,分为汇编器的链接视角与程序的执行视角两种去分析ELF文件。

从程序执行视角来说,这就是Linux加载器加载的各种Segment的集合。比如只读代码段、数据的读写段、符号段等等。而从链接的视角上来看,elf又分为各种的sections。

注意Section Header Table和Program Header Table并不是一定要位于文件开头和结尾的,其位置由ELF Header指出,上图这么画只是为了清晰。

为了彻底的弄清楚elf文件的内容,可以先从ELF文件的头部开始分析。

3.elf文件的头部信息

对于elf头部文件信息,首先可以可以查看一下内存的布局情况:

根据readelf可以得到该文件的头部信息的情况。

根据定义,elf32的结构体定义,在Linux上可以在/usr/include/elf.h中找到

#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;

上述的Elf32_Half定义

/* Type for a 16-bit quantity.  */
typedef uint16_t Elf32_Half;

其中Elf32_Word的定义

/* Types for signed and unsigned 32-bit quantities.  */
typedef uint32_t Elf32_Word;

然后Elf32_AddrElf32_Off定义

/* Type of addresses.  */
typedef uint32_t Elf32_Addr;

/* Type of file offsets.  */
typedef uint32_t Elf32_Off;

有了这些数据结构的信息,然后对应具体的数据细节如下:

  • e_ident[EI_NIDENT]

文件的标识以及标识描述了elf如何编码等信息。

Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00

关于该结构体的索引可以看下面的表格:

名称 取值 目的
EI_MAG0 0 文件标识(0x7f)
EI_MAG1 1 文件标识(E)
EI_MAG2 2 文件标识(L)
EI_MAG3 3 文件标识(F)
EI_CLASS 4 文件类
EI_DATA 5 数据编码
EI_VERSION 6 文件版本
EI_PAD 7 补齐字节开始处
EI_NIDENT 16 e_ident[]大小

EI_CLASS的内容,当取值为0时,是非法类别,1是32位的目标,2是64位的目标。这里是1所以程序是32位的目标。

EI_DATA表示数据的编码,当为0时,表示非法数据编码,1表示高位在前,2表示低位在前。

EL_VERSION表示了elf的头部版本号码。

前面四个基本上确定的,内容第一个字符为7f,后面用ELF字符串表示该文件为ELF格式。

  • e_type

该数据类型是uint16_t数据类型的,占两个字节。通过字段查看,可以看到这个值为00 02。表格定义如下:

名称 取值 含义
ET_NONE 0x0000 未知目标文件格式
ET_ERL 0x0001 可重定位文件
ET_EXEC 0x0002 可执行文件
ET_DYN 0x0003 共享目标文件
ET_CORE 0x0004 Core文件(转储格式)
ET_LOPROC 0xff00 特定处理器文件
ET_HIPROC 0xffff 特定处理器文件

对应表格内容,可以看到类型为EXEC即可执行文件类型。

  • e_machine

由字段可以看到为00 28,关于这个字段的解析,基本上就是表示该elf文件是针对哪个处理器架构的。

下面只列出几个常见的架构的序号

名称 取值 含义
EM_NONE 0 No machine
EM_SPARC 2 SPARC
EM_386 3 Intel 80386
EM_MIPS 8 MIPS I Architecture
EM_PPC 0x14 PowerPC
EM_ARM 0x28 Advanced RISC Machines ARM

通过上述的表格,可以看到该架构是ARM处理器上运行的程序。

  • e_version

该字段占四个字节,表示当前文件版本的信息。现在取值为00 00 00 01。从取值上来看

名称 取值 含义
EV_NONE 0 非法版本
EV_CURRENT 1 当前版本
  • e_entry

这里表示程序的入口地址,目前为四字节,所以通过字段解析到的内容为00 00 80 00。得到可执行程序的入口地址为0x8000

  • e_phoff

该字段表示程序表头偏移。占四个字节,根据字段解析,可以查看当前的偏移量为00 00 00 34。也就是实际的偏移量为52个字节。这52个字节其实就是头部的信息数据结构体的大小。

  • e_shoff

该区域比较重要,记录了section的偏移地址。为四字节,解析出来的字段为0x00 04 24 5c。所以得到地址为0x4245c。

根据这个偏移得到section的内容:

通过readelf -t也可以得到类似的结果。

关于节区如何解析。后面再进行描述。

  • e_flags

特定处理器格式的标志,这里的字段解析为05 00 02 00。与特定的处理器相关。

  • e_ehsize

elf文件的头部大小。该取值与头文件结构体的大小相关,目前为52字节,即00 34

  • e_phentsize

程序头部表项大小,当前取值为00 20,为32个字节,这里表示

关于程序表项的解析,后面再进行具体分析。

  • e_phnum

目前取值为00 01,这里表示程序头的个数当前只有一个程序头,如果有多个程序头表,那么会在elf头文件之后,也就是52个字节之后,依次向下排列。因为这里是1,所以只有1个程序头。

  • e_shentsize

表示节区头部表格大小,解析字段为00 28,也就是第一个节区的大小为40个字节的偏移处。根据e_shoff可以知道。

将从e_shoff的区域向后面偏移40个字节,得到第一个节区的内容。

  • e_shnum

节区的数量,由字段解析得到数据为00 11。此时得到节区的数量为17个。通过readelf -t也可以解析到节区的数量为17个。

bigmagic@bigmagic:~/work/python_elf/elf$ readelf -t rtthread.elf 
There are 17 section headers, starting at offset 0x4245c:
  • e_shstrndx

标记字符串节区的索引。当前的解析为00 0e。也就是14个节区为字符节区。

到这里,头部信息的相关字段就解析完成了。

4.elf文件的节区(Section)

elf文件中的节是从编译器链接角度来看文件的组成的。从链接器的角度上来看,包括指令、数据、符号以及重定位表等等。

4.1 节区的作用

在可从定位的可执行文件中,节区描述了文件的组成,节的位置等信息。通过readelf -s可以查看信息。

这些节信息通过特定的地址偏移组成了一个elf文件的整体。

4.2 节区的组成

关于理解ELF中的Section。首先需要知道程序的链接视图,在编译器将一个一个.o文件链接成一个可以执行的elf文件的过程中,同时也生成了一个表。这个表记录了各个Section所处的区域。在程序中,程序的section header有多个,但是大小是一样。拿elf32文件来说

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;

根据e_shoff可以找到section的地址,根据e_shentsize可以找到具体的第一个section的内容。

如果要找到每个段的具体细节,首先可以根据e_shstrndx找到节的字段。由于e_shstrndx=14。而且每个为40字节。那么一共是560字节的偏移。从e_shoff的地址0x4245c开始,首先偏移了e_shentsize也就是40个字节。然后向下得到40x14个Section表项。最后可以得到e_shstrndx对应的节区。

为什么首先需要得到这个字符串节区,通过这个就可以得到节区的名字了。然后通过计算,节区字符串存在的区域:

每个字符串以\0结尾。大小为0000ab也就是171个字节。接下来我们来举个具体的例子来解析Section。比如要读取.text的段。那么首先看一下细节。

首先从字段结构体上进行分析:

  • sh_name

表示从e_shstrndx的偏移地址开始,得到的字符字符串信息为该段的名字。目前解析到的为0x1b。最后算出得到实际的名称为.text。

  • sh_type

字段的类型为01,关于sh_type的类型,解析如下:

/* Legal values for sh_type (section type).  */

#define SHT_NULL            0        /* Section header table entry unused */
#define SHT_PROGBITS        1        /* Program data */
#define SHT_SYMTAB          2        /* Symbol table */
#define SHT_STRTAB          3        /* String table */
#define SHT_RELA            4        /* Relocation entries with addends */
#define SHT_HASH            5        /* Symbol hash table */
#define SHT_DYNAMIC         6        /* Dynamic linking information */
#define SHT_NOTE            7        /* Notes */
#define SHT_NOBITS          8        /* Program space with no data (bss) */
#define SHT_REL             9        /* Relocation entries, no addends */
#define SHT_SHLIB          10        /* Reserved */
#define SHT_DYNSYM         11        /* Dynamic linker symbol table */
#define SHT_INIT_ARRAY     14        /* Array of constructors */
#define SHT_FINI_ARRAY     15        /* Array of destructors */
#define SHT_PREINIT_ARRAY  16        /* Array of pre-constructors */
#define SHT_GROUP          17        /* Section group */
#define SHT_SYMTAB_SHNDX   18        /* Extended section indeces */
#define    SHT_NUM         19        /* Number of defined types.  */
#define SHT_LOOS           0x60000000    /* Start OS-specific.  */
#define SHT_GNU_ATTRIBUTES 0x6ffffff5    /* Object attributes.  */
#define SHT_GNU_HASH       0x6ffffff6    /* GNU-style hash table.  */
#define SHT_GNU_LIBLIST    0x6ffffff7    /* Prelink library list */
#define SHT_CHECKSUM       0x6ffffff8    /* Checksum for DSO content.  */
#define SHT_LOSUNW         0x6ffffffa    /* Sun-specific low bound.  */
#define SHT_SUNW_move      0x6ffffffa
#define SHT_SUNW_COMDAT    0x6ffffffb
#define SHT_SUNW_syminfo   0x6ffffffc
#define SHT_GNU_verdef     0x6ffffffd    /* Version definition section.  */
#define SHT_GNU_verneed    0x6ffffffe    /* Version needs section.  */
#define SHT_GNU_versym     0x6fffffff    /* Version symbol table.  */
#define SHT_HISUNW         0x6fffffff    /* Sun-specific high bound.  */
#define SHT_HIOS           0x6fffffff    /* End OS-specific type */
#define SHT_LOPROC         0x70000000    /* Start of processor-specific */
#define SHT_HIPROC         0x7fffffff    /* End of processor-specific */
#define SHT_LOUSER         0x80000000    /* Start of application-specific */
#define SHT_HIUSER         0x8fffffff    /* End of application-specific */

当前为1,所以得到数据为程序数据。比如.text .data .rodata等等。

  • sh_flags

表示段的标志,A表示分配的内存、AX表示分配可执行、WA表示分配内存并且可以修改。

  • sh_addr

加载后程序段的虚拟地址

  • sh_offset

表示段在文件中的偏移。

  • sh_size

段的长度

  • sh_addralign

段对齐

  • sh_entsize

每项固定的大小

5.elf文件的段(Segment)

关于Linking ViewExecution View的具体含义,可以查看

http://www.skyfree.org/linux/references/ELF_Format.pdf

这里有一张图值得研究一下:

对于链接视图,也就是我们前面分析的Section,可以理解目标代码文件的内容布局。而右边的ELF的执行视图,则可以理解为可执行的文件内容布局。链接视图由sections组成,而可执行的文件的内容由segment组成。

两者是有一些区别的,我们平时在进行程序构建的时候理解的.text、.bss、.data段,这些都是section,也就节区的概念。这些段通过section header table进行组织与重定位。

但是对于segment来说,程序代码段、数据段是Segment。代码段又可以分为.text,数据段又分为.data、.bss等。

通过readelf -l可以查看具体的可执行文件的细节。

这里的信息和程序的加载直接相关。具体的elf文件加载过程这篇文章不会多说,后面会写文章专门叙述。本文的目的是elf文件格式的解析过程。

6.用python解析elf文件

为了验证上述的分析过程是否合理,可以通过python脚本来解析elf文件。得到elf文件相关的信息。目前采用的是python3进行解析。

第一步:程序组织

当前组织的程序分为三步:

1.校验elf文件

2.显示elf头部信息

3.解析段信息

if __name__ == '__main__':
 file = sys.argv[1]
 verify_elf(file)
 display_elfhdr(file)
 display_sections(file)

首先需要导入sys模块import sys

当程序执行的时候输入python elf_parse.py rtthread.elf就可以向下执行了。

第二步:校验elf

该函数的作用主要是校验elf文件,并且将相关的信息存到字典里面。

elfhdr = {}
def verify_elf(filename):
 f = open(filename,'rb')
 elfident = f.read(16)
 magic = [i for i in elfident]
 if( magic[0] != 127 or magic[1]!= ord('E') or magic[2] != ord('L') or magic[3] != ord('F')):
  print ("your input file %s not a elf file" %filename)
  return
 else:
  temp = f.read(struct.calcsize('2H5I6H'))
  temp = struct.unpack('2H5I6H',temp)
  global elfhdr
  elfhdr['magic'] = magic
  elfhdr['e_type']= temp[0]
  elfhdr['e_machine'] = temp[1]
  elfhdr['e_version'] = temp[2]
  elfhdr['e_entry'] = temp[3]
  elfhdr['e_phoff'] = temp[4]
  elfhdr['e_shoff'] = temp[5]
  elfhdr['e_flags'] = temp[6]
  elfhdr['e_ehsize'] = temp[7]
  elfhdr['e_phentsize'] = temp[8]
  elfhdr['e_phnum'] = temp[9]
  elfhdr['e_shentsize'] = temp[10]
  elfhdr['e_shnum'] = temp[11]
  elfhdr['e_shstrndx'] = temp[12]
 f.close()

校验的方法是读取前面的四个字节,是否第一个字节为7E,后面为ELF字符,如果满足,则表示为ELF文件。

后面是将数组进行了一个填充。

第三步:展示elf文件的头部信息

def display_elfhdr(elffile):
 global elfhdr
 print ("ELF Header")
 magic = elfhdr['magic']
 print ("  Magic:  %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" %(magic[0] ,magic[1],magic[2],magic[3],magic[4],magic[5],magic[6],magic[7],magic[8],magic[9],magic[10],magic[11],magic[12],magic[13],magic[14],magic[15]))
 if magic[4] == 1 :
  print ("  Class:                           ELF32")
 else:
  print ("  Class:                           ELF64")
 if magic[5] == 1 :
  print ("  Data:                            2's complement,little endian")
 else:
  print ("Data:                              2's complement,bigendian")
 print ("  Version:                         %d(current)" %magic[6])
 if magic[7] == 0:
  os_abi = 'System V ABI'
 elif magic[7]== 1:
  os_abi = 'HP-Ux operating system'
 elif magic[7] == 255:
  os_abi = 'Standalone (embedded) application'
 print ("  OS/ABI:                          %s" %os_abi)
 print ("  ABI Version:                     %d" %magic[8])
 if elfhdr['e_type'] == 0:
  type = 'No file type'
 elif elfhdr['e_type'] == 1:
  type = 'Relocatable object file'
 elif elfhdr['e_type'] == 2:
  type = 'Executable file'
 elif elfhdr['e_type'] == 3:
  type = 'Core file'
 print ("  Type:                            %s" %type)
 print ("  Machine:                         %d" %elfhdr['e_machine'])
 print ("  Version:                         0x%x" %elfhdr['e_version'])
 print ("  Entry point address:             0x%x" %elfhdr['e_entry'])
 print ("  Start of program headers:        %d (bytes into file)" %elfhdr['e_phoff'])
 print ("  Start of section headers:        %d (bytes into file)" %elfhdr['e_shoff'])
 print ("  Flags:                           0x%x" %elfhdr['e_flags'])
 print ("  Size of this header:             %d (bytes)" %elfhdr['e_ehsize'])
 print ("  Size of program headers:         %d (bytes)" %elfhdr['e_phentsize'])
 print ("  Number of program headers:       %d " %elfhdr['e_phnum'])
 print ("  Size of section headers:         %d (bytes)" %elfhdr['e_shentsize'])
 print ("  Number of section headers:       %d" %elfhdr['e_shnum'])
 print ("  Section header string table index: %d"%elfhdr['e_shstrndx'])

该函数主要是解析了elf头部信息中对应的相关字节,并且做了解析过程。

第四步:解析sections

在解析具体的段的时候,主要是利用地址偏移找到相关的符号表名称,然后根据偏移算出细节。

def display_sections(elffile):
 verify_elf(elffile)
 sections = []
 global elfhdr
 sec_start = elfhdr['e_shoff']
 sec_size = elfhdr['e_shentsize']
 f = open(elffile,'rb')
 f.seek(sec_start)
 for i in range(0,elfhdr['e_shnum']):
  temp = f.read(sec_size)
  temp = struct.unpack('10I',temp)
  sec = {}
  sec['sh_name'] = temp[0]
  sec['sh_type'] = temp[1]
  sec['sh_flags'] = temp[2]
  sec['sh_addr'] = temp[3]
  sec['sh_offset'] = temp[4]
  sec['sh_size'] = temp[5]
  sec['sh_link'] = temp[6]
  sec['sh_info'] = temp[7]
  sec['sh_addralign'] = temp[8]
  sec['sh_entsize'] = temp[9]
  sections.append(sec)
 print ("There are %d section headers,starting at offset 0x%x:\n" %(elfhdr['e_shnum'],sec_start))
 print ("Section Headers:")
 print ("  [Nr] Name               Type            Address          Offset")
 print ("       Size               Entsize         Flags  Link  Info Align")
 start = sections[elfhdr['e_shstrndx']]['sh_offset']
 for i in range(0,elfhdr['e_shnum']):
  offset = start + sections[i]['sh_name']
  name = get_name(f,offset)
  type2str = ['NULL','PROGBITS','SYMTAB','STRTAB','RELA','HASH','DYNAMIC','NOTE','NOBITS','REL','SHLIB','DYNSYM']
  flags = sections[i]['sh_flags']
  if (flags == 1):
   flagsstr = 'W'
  elif (flags == 2):
   flagsstr = 'A'
  elif (flags == 4):
   flagsstr = 'X'
  elif (flags == 3):
   flagsstr = 'W' + 'A'
  elif (flags == 6):
   flagsstr = 'A' +  'X'
  elif (flags == 0x0f000000 or flags == 0xf0000000):
   flagsstr = 'MS'
  else:
   flagsstr = ''
  print ("  [%d]  %s              %s             %x             %x" %(i,str(name,encoding='utf-8'),type2str[sections[i]['sh_type'] & 0x7],sections[i]['sh_addr'],sections[i]['sh_addralign']))
  print ("      %x                   %x       %s        %d     %d     %x" %(sections[i]['sh_size'],sections[i]['sh_entsize'],flagsstr,sections[i]['sh_link'],sections[i]['sh_info'],sections[i]['sh_addralign']))
 f.close()
def get_name(f,offset):
 name = b''
 f.seek(offset)
 while 1:
  c = f.read(1)
  if c == b'\x00':
   break
  else:
   name += c
 return name

第五步:结果展示

上述过程如果无误,那么可以看到解析出来的elf文件信息了。

这样就完成了一个elf文件的解析过程。

7.总结

ELF文件经常的见到,但是要具体的分析ELF文件中所对应的具体的含义却需要费一番功夫。本文主要通过对elf文件的构造、具体的含义以及如何去分析elf文件的角度,全面的进行elf文件格式的剖析。在程序链接、程序加载执行上会有更多不一样的理解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ELF文件格式的详解 的相关文章

  • Nacos介绍以及使用

    目录 一 概述 1 1 Nacos是什么 能干嘛 1 2 去哪下载 1 3 各个注册中心比较 二 Nacos作为服务注册中心 2 1 基于Nacos的服务提供者 2 2 基于Nacos的服务消费者 三 Nacos作为服务配置中心 3 1 N
  • 基于深度学习的海上雷达数据质量管控自动化技术

    文章作者Rune Gangeskar任职于Miros公司 目标是设计一套Wavex传感器系统 如何精准测量波浪 洋流 以及对水航速 并使用深度学习网络来自动辨识测量下取得的雷达数据 进一步提升Wavex系统的表现与可靠度 一 总体简介 对海
  • Java实现不规则软件版本号比较大小

    背景 最近由于需要比较两个版本号 从网上寻找的例子出现了问题 因此单独写一个不规则的版本号比较方法 代码 如果version1大于等于version2就返回true 可以根据自己需要进行调整 public static boolean co

随机推荐

  • 使用 Simulink 进行 STM32 编程

    目录 介绍 所需材料 步骤 1 在MATLAB中设置STM32 MAT软件路径 步骤 2 在STM32CubeMX中创建一个项目 步骤 3 配置时钟和 GPIO 引脚 步骤 4 项目经理并生成代码 步骤 5 在 Simulink 中创建模型
  • Java多线程——线程同步

    1 不安全的买票 不安全的买票 线程不安全 有负数或者多人买到同一张票 public class UnsafeBuyTicket public static void main String args BuyTicket buyTicket
  • $ 与 $$(*) 是什么?

    前言 今天在阅读一篇文章 小伙伴遇到这个问题说不想干前端了 一次Chrome翻译造成的玄学bug 主要内容是说翻译插件引发页面的react报错 文章中用 去获取报错页面所有的dom标签和正常无报错页面的dom标签 再进行对比来定位问题 具体
  • webform jquery ajax,ajax - Asp.net webform, jquery - Stack Overflow

    I m working on a project of estimation for my office I m using Ajax Autocomplete in Visual Studio 2017 The following cod
  • 第九章:构造器与垃圾收集器-对象的前世今生

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 第九章 构造器与垃圾收集器 对象的前世今生 对象有生有死 必须对对象的生命周期负责 何时创建 何时销毁 不是消灭 只是放弃 由垃圾收集器 GC 将它蒸发掉 回收所占空
  • git命令总结

    1 git init 在当前目录下创建新的git仓库 2 git add filename 文件版本控制之前需要对这些文件进行追踪 对filename进行追踪 将文件添加进入缓存 3 git commit 提交更新 git commit a
  • IPv4 地址已耗尽,IPv6 涅槃重生:腾讯云IPv6改造综述

    引言 近日 全球 IPv4 地址正式耗尽的消息刷遍各大技术媒体 IPv6 再一次被推到人们面前 IP 作为网络世界的通行证 其重要性不言而喻 IPv4 地址枯竭 IPv6 作为IPv4地址枯竭的解决方案 其在中国的发展历程是怎样的 产品环环
  • 微信小程序开源项目精选

    本期为大家精选了码云上优秀的微信小程序开源项目 包括电商 博客 框架 建站系统 日常工具 图像识别等 希望能够给大家带来一点帮助 1 项目名称 微信电商小程序 作者 三三网络科技 项目简介 此项目是一套完整的电商系统 并且兼容各种电商场景可
  • 粒子滤波原理及其matlab仿真

    Github个人博客 https joeyos github io 粒子滤波原理及其matlab仿真 系统建模 粒子滤波算法不受线性高斯模型的约束 与卡尔曼滤波器一样 粒子滤波算法同样需要知道系统的模型 如果不知道系统的模型 也要想办法构建
  • Ubuntu 22.04 解决使用 .AppImage 文件方法

    AppImages 是一个文件系统 需要 FUSE 版本为 2 才能运行 但是 Ubuntu 22 04 的发行版本没有对其进行原始的配置的安装 重新安装并且配置即可 终端问题 未加载到 libfuse so 2 软连接 所以无法执行 Ap
  • C++对csv文件的读写

    include
  • 如何在线免费将MP4转换成MP3格式音乐

    MP4已经成为互联网上最流行的视频格式 我们从各种视频资源网站上下载到的视频文件大部分都是以MP4格式存储的 尤其是一些高品质的歌曲MV 为了达到在高压缩的前提下得到最好的质量 几乎都是mp4文件 但是如果你想直接在手机或者车上听这些歌曲
  • 【Mac】【Git】 全局配置 忽略 .DS_Store

    DS Store 是什么 Mac OS X 使用 DS Store 文件来存储文件夹特定的元数据信息 它们是在 Mac OS X Finder 访问的每个文件夹中创建的 甚至是网络宗卷和外部设备 文件夹级别的自定义存储在 DS Store
  • Vue锚链接(两种方法) scrollIntoView

    第一种 常见 锚链接 id和 href 结合起来 div style height 300px 第一 div div style height 300px 第二 div a href one 回到第一 a a href two 回到第二 a
  • 直流电源_滤波电路

    目录 前言 电容滤波电路 1 滤波原理 2 输出电压平均值 3 脉动系数 4 整流二极管的导通角 5 电容滤波电路的输出特性和滤波特性 倍压整流电路 其他形式的滤波电路 1 电感滤波电路 2 复式滤波电路 3 各种滤波电路的比较 前言 整流
  • 较好用的html5编译器

    一 BlueGriffon 基于 Firefox 渲染引擎的下一代 Web 和 EPUB 编辑器 链接 BlueGriffon 二 Aloha Editor 基于 所见即所得 的原则 HTML5 编辑器可以直接在门户网站上编辑网站 快速 简
  • 计算方法--解线性方程组的直接法

    文章目录 一 Gauss 消元法 1 顺序高斯消元法 总计算量 2 主元素高斯消元法 列主元素高斯消元法 3 高斯 约当 Gauss Jordan 消去法 总计算量 二 矩阵三角分解法 1 直接三角分解法 LU分解 Doolittle分解
  • WIN10安装后必做的优化,解决卡顿问题

    WIN10安装后必做的优化 解决卡顿问题
  • 储存过程之拉链表

    很多做数仓的朋友在面试的时候都会被问到 你写过的最难的存储过程是什么 这时候我们都会想到拉链表 拉链表真的那么难吗 下面我简单介绍一下拉链表作用 以及制作思路 希望可以帮到你 拉链表的作用 数据进行增量或者全量同步时 我们希望保留少数字段历
  • ELF文件格式的详解

    1 说明 2 elf文件的基本格式 3 elf文件的头部信息 4 elf文件的节区 Section 4 1 节区的作用 4 2 节区的组成 5 elf文件的段 Segment 6 用python解析elf文件 7 总结 1 说明 ELF的英