Windows编程系列:PE文件结构

news2024/11/26 3:49:31

Windows编程系列:PE文件结构

PE文件结构

Portable Executable (PE),可移植的可执行文件。在Windows平台下,所有的可执行文件(包括.exe, .dll, .sys, .ocx, .com等)均使用PE文件结构。这些使用了PE文件结构的可执行文件也称为PE文件。

PE结构包含的结构体有DOS头,PE标识 、文件头、可选头、目录头、目录结构、节表等
整体结构如下:
在这里插入图片描述

从上图可以看出PE结构分为4大部分,其中每个部分又进行了细分。

从数据管理的角度来看,可以把PE文件大致分为两部分,

1、DOS头、PE头和节表属于PE文件的数据管理结构或数据组织结构部分,

2、节表数据才是PE文件真正的数据部分,其中包含着代码、数据、资源等内容。

DOS头

DOS头分为“MZ头部”和"DOS存根“。

”MZ头部“是真正的DOS头部,由于其开始处的两个字节为"MZ",因此DOS头也可以叫作MZ头部。

这个我们用十六进制编辑器随便打开一个exe就可以看到
在这里插入图片描述
该部分用于程序在DOS系统下加载,它的结构被定义为IMAGE_DOS_HEADER

IMAGE_DOS_HEADER定义

//大小为: 0x40(64)字节
 #define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
 +0h   WORD   e_magic;                     // MZ标记 0x5a4d
 +2h   WORD   e_cblp;                      // 最后(部分)页中的字节数
 +4h   WORD   e_cp;                        // 文件中的全部和部分页数
 +6H   WORD   e_crlc;                      // 重定位表中的指针数
 +8H   WORD   e_cparhdr;                   // 头部尺寸以段落为单位
 +0aH   WORD   e_minalloc;                  // 所需的最小附加段
 +0cH   WORD   e_maxalloc;                  // 所需的最大附加段
 +0eH   WORD   e_ss;                        // 初始的SS值(相对偏移量)
 +10H   WORD   e_sp;                        // 初始的SP值
 +12H   WORD   e_csum;                      // 补码校验值
 +14H   WORD   e_ip;                        // 初始的IP值
 +16H   WORD   e_cs;                        // 初始的SS值
 +18H   WORD   e_lfarlc;                    // 重定位表的字节偏移量
 +1aH   WORD   e_ovno;                      // 覆盖号
 +1cH   WORD   e_res[4];                    // 保留字
 +24H   WORD   e_oemid;                     // OEM标识符(相对m_oeminfo)
 +26H   WORD   e_oeminfo;                   // OEM信息
 +29H   WORD   e_res2[10];                  // 保留字
 +3CH   LONG   e_lfanew;                    // NT头(PE标记)相对于文件的偏移地址
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

DOS存根是一段简单的程序,主要用于输出“This program cannot be run in DOS mode.”类似的提示字符串。

为什么PE结构的最开始位置有这样一段DOS头部呢?

为了该可执行程序可以兼容DOS系统。通常情况下,Win32下的PE程序不能在DOS下运行,因此保留了这样一个简单的DOS程序用于提示“不能运行于DOS模式下”。

+3CH LONG e_lfanew; // NT头(PE标记)相对于文件的偏移地址
+3CH 开始的四个字节标识PE头开始
在这里插入图片描述

PE头解析

在这里插入图片描述

PE文件头由PE文件头标志,标准PE头,扩展PE头三部分组成。PE文件头标志自然是50 40 00 00,也就是’PE’,我们从结构体的角度看一下PE文件头的详细信息

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature; 						//PE文件头标志 => 4字节
    IMAGE_FILE_HEADER FileHeader; 			//标准PE头 => 20字节
    IMAGE_OPTIONAL_HEADER32 OptionalHeader; //扩展PE头 => 32位下224字节(0xE0) 64位下240字节(0xF0)
} IMAGE_N

PE头签名(4个字节)

在这里插入图片描述

文件头IMAGE_FILE_HEADER(20字节)

IMAGE_FILE_HEADER是IMAGE_NT_HEADERS结构体中的一个结构,紧接在PE标识符(Signature字段)的后面。
IMAGE_FILE_HEADER占用20个字节
在这里插入图片描述

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine; 				//可以运行在什么平台上 任意:0 ,Intel 386以及后续:14C x64:8664
    WORD    NumberOfSections; 		//节的数量  区段数
    DWORD   TimeDateStamp; 			//编译器填写的时间戳,什么时间被创建
    DWORD   PointerToSymbolTable;   //调试相关
    DWORD   NumberOfSymbols; 		//调试相关
    WORD    SizeOfOptionalHeader;   //标识扩展PE头大小
    WORD    Characteristics;        //文件属性 => 16进制转换为2进制根据哪些位有1,可以查看相关属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
Machine(1字节),标识在什么机器上运行

WORD 2字节,该字段表示可执行文件的目标CPU类型,取值如下:
在这里插入图片描述

这里我们看到的是64 86,也就是可以在上述对应环境运行在这里插入图片描述

NumberOfSections:WORD 2字节

该字段表示PE文件的节区的个数.请注意,Windows 加载程序将节区限制为 96。
该字段的值为06 00,即为0x00000006,表示该PE文件的节区有6个。
在这里插入图片描述
.txt 代码段
.data 可读写的数据段
.rdata 只读写的数据段
.pdata 节是由用于异常处理的函数表项组成的数组
.idata 导入数据段
.edata 导出数据段
.rsrc资源段
.reloc 主要用于存储基址重定位表
使用工具LordPE可以看到有6个节区
在这里插入图片描述

TimeDataStamp:

DWORD 4字节,该字段表示 文件是何时被创建的,这个值是自1970/1/1以来用格林威治时间计算的秒数。
在这里插入图片描述
界面上可以看到这个字段的取值是0xC2B75AE3,我们写一个简单的程序计算一下

import datetime

# 给定的十六进制数
hex_seconds_since_epoch = 0xC2B75AE3

# 将十六进制转换为十进制
decimal_seconds_since_epoch = int(hex_seconds_since_epoch)

# 创建一个表示Unix纪元的datetime对象
epoch = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)

# 从Unix纪元开始增加秒数
dt = epoch + datetime.timedelta(seconds=decimal_seconds_since_epoch)

# 增加8小时来调整时区
dt_with_offset = dt.astimezone(tz=datetime.timezone(datetime.timedelta(hours=8)))

# 打印结果
print(dt_with_offset.strftime('%Y-%m-%d %H:%M:%S %Z%z'))

在这里插入图片描述

PointerToSymbolTable:

DWORD 4字节,符号表的偏移量(以字节为单位),如果没有 COFF 符号表,则为零。
在这里插入图片描述

NumberOfSymbols

DWORD 4字节,符号表中的符号数。
在这里插入图片描述

SizeOfOptionalHeader

WORD 2字节,该字段 指定IMAGE_OPTIONAL_HEADER结构的大小。
在这里插入图片描述
我们这里的值是F0 00,也就是0x000000F0。

注意:在计算IMAGE_OPTIONAL_HEADER的大小时,应该取SizeOfOptionalHeader的值,而不是使用sizeof()函数。

因为IMAGE_OPTIONAL_HEADER结构体的大小可能是会改变的。

Characteristics

WORD 2字节,指定文件的类型。取值如下:
在这里插入图片描述

我们这里是22 00 ,也就是0x00000022,这是一个组合值(IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE),代表这是一个可执行文件,且能处理超过2GB的内存。
在这里插入图片描述

可选头IMAGE_OPTIONAL_HEADER

可选头IMAGE_OPTIONAL_HEADER是IMAGE_NT_HEADERS结构体中的一个结构,紧接在IMAGE_FILE_HEADER类型之后。

可选头是对文件头的一个补充。文件头主要描述文件的相关信息,而可选头主要用来管理PE文件被操作系统装载时所需要的信息。

IMAGE_OPTIONAL_HEADER在现在的大部分资料中都被称为可选头。但该头部实际上是一个必须存在的头。

所以这里应该是最初在翻译时或者其它方面导致的错误,后人一直沿用了。Option也有选项之类的意思 。

IMAGE_OPTIONAL_HEADER的大小在IMAGE_FILE_HEADER的SizeOfOptionalHeader字段中给出。

我们这里的值是F0 00,也就是IMAGE_OPTIONAL_HEADER的大小是0x000000F0。
在这里插入图片描述

IMAGE_OPTIONAL_HEADER(可选头)在IMAGE_FILE_HEADER(文件头)之后

IMAGE_FILE_HEADER的结束位置在0x000010F,那么可选头的起始位置是0x00000110

通过下面的图可以比较清晰的看到
在这里插入图片描述
选头的结束位置是0x00000110 + 0x000000F0 -1 = 0x000001FF,如下图所示
在这里插入图片描述通常情况下,可选头的结尾后面跟的是第一项节表的名称,就是值为.text的位置。
如上图所示:文件偏移0x0000200处的节点名称为".text",也就是说,可选头的结束位置在0x0000200偏移的前一字节,即0x00001FF
下面我们来详细看一下IMAGE_OPTIONAL_HEADER的定义

IMAGE_OPTIONAL_HEADER实际是一个宏,定义如下:

1 #ifdef _WIN64
2 typedef IMAGE_OPTIONAL_HEADER64             IMAGE_OPTIONAL_HEADER;
3 #else
4 typedef IMAGE_OPTIONAL_HEADER32             IMAGE_OPTIONAL_HEADER;
5 #endif

这里我们以x64为例,所以使用的是IMAGE_OPTIONAL_HEADER64类型,定义如下

typedef struct _IMAGE_OPTIONAL_HEADER64 {
    WORD        Magic;
    BYTE        MajorLinkerVersion;
    BYTE        MinorLinkerVersion;
    DWORD       SizeOfCode;
    DWORD       SizeOfInitializedData;
    DWORD       SizeOfUninitializedData;
    DWORD       AddressOfEntryPoint;
    DWORD       BaseOfCode;
    ULONGLONG   ImageBase;
    DWORD       SectionAlignment;
    DWORD       FileAlignment;
    WORD        MajorOperatingSystemVersion;
    WORD        MinorOperatingSystemVersion;
    WORD        MajorImageVersion;
    WORD        MinorImageVersion;
    WORD        MajorSubsystemVersion;
    WORD        MinorSubsystemVersion;
    DWORD       Win32VersionValue;
    DWORD       SizeOfImage;
    DWORD       SizeOfHeaders;
    DWORD       CheckSum;
    WORD        Subsystem;
    WORD        DllCharacteristics;
    ULONGLONG   SizeOfStackReserve;
    ULONGLONG   SizeOfStackCommit;
    ULONGLONG   SizeOfHeapReserve;
    ULONGLONG   SizeOfHeapCommit;
    DWORD       LoaderFlags;
    DWORD       NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

成员说明:

Magic

WORD 2字节,文件的状态类型,它可以是以下值之一
在这里插入图片描述
在这里插入图片描述
我们这里的值是0B 02,实际取值是0x0000020B,所以这是一个64位的可执行文件。

MinorLinkerVersion:链接器的次版本号

SizeOfCode:代码节的大小(以字节为单位),如果有多个代码块,则为所有此类块的总和。

SizeOfInitializedData:初始化的数据块的大小(以字节为单位),如果有多个已初始化的数据块,则为所有此类块的总和。

SizeOfUninitializedData:未初始化数据块的大小(以字节为单位),如果有多个未初始化的数据块,则为所有此类块的总和。

AddressOfEntryPoint:指向入口点函数(相对于映像基址)的指针。 对于可执行文件,这是起始地址。 对于设备驱动程序,这是初始化函数的地址。 入口点函数对于 DLL 是可选的。 如果没有入口点,则此成员为零。

BaseOfCode:指向代码部分开头(相对于映像基址)的指针。

ImageBase:文件被装入内存后的首选建议装载地址。对于EXE文件来说,通常情况下,该地址就是装载地址;对于DLL文件来说,可能就不是其装入内存后的地址了。

SectionAlignment:节表被装入内存后的对齐值。节表被映射到内存中需要对其的单位。在Win32下,通常情况下,该值为0x1000,也就是4KB大小。Windows操作系统的内存分页一般为4KB。此值必须大于或等于 FileAlignment 成员。

FileAlignment:节表在文件中的对齐值。通常情况下,该值为0x1000或0x200。在文件对齐值为0x1000时,由于与内存对齐值相同,可以加快装载速度。
而文件对齐值为0x200时,可以占用相对较少的磁盘空间。0x200是512字节,通常磁盘的一个扇区即为512字节。
说明:

程序无论是在内存中还是磁盘上,都无法恰好满足SectionAlignment和FileAlignment值的倍数,在不足的情况下需要补0值,这样就导致节与节之间存在了无用的空隙。这些空隙对于病毒之类程序而言就有了可利用的价值。
MajorOperatingSystemVersion:要求最低操作系统的主版本号。

MinorOperatingSystemVersion:要求最低操作系统的次版本号。

MajorImageVersion:可执行文件的主版本号。

MinorImageVersion:可执行文件的次版本号。

MajorSubsystemVersion:子系统的主版本号。

MinorSubsystemVersion:子系统的次要版本号。

Win32VersionValue:此成员为保留成员,必须为 0。

SizeOfImage:可执行文件装入内存后的总大小。该大小按内存对齐方式(SectionAlignment )对齐。

SizeOfHeaders:整个PE头部的大小。这个PE头部泛指DOS头、PE头、节表的总和大小。舍入为 FileAlignment 成员中指定的值的倍数。

CheckSum:校验和值。对于EXE文件通常为0;对于SYS文件,则必须有一个校验和。

SubSystem:运行此映像所需的子系统。 定义了以下值。
在这里插入图片描述
DllCharacteristics:指定DLL文件的特征,该值大部分时候为0,系统定义了以下值
在这里插入图片描述
SizeOfStackReserve:要为堆栈保留的字节数。 加载时只提交 由 SizeOfStackCommit 成员指定的内存;其余部分一次提供一页,直到达到此保留大小。

SizeOfStackCommit:要为堆栈提交的字节数。

SizeOfHeapReserve:要为本地堆保留的字节数。 加载时仅提交 由 SizeOfHeapCommit 成员指定的内存;其余部分一次提供一页,直到达到此保留大小。

SizeOfHeapCommit:要为本地堆提交的字节数。

LoaderFlags:此成员已过时。

NumberOfRvaAndSizes:数据目录项的个数。该个数在PSDK中有一个宏定义,

DataDirectory:数据目录表,由NumberOfRvaAndSizes个IMAGE_DATA_DIRECTORY结构体组成。该数组包含输入表、输出表、资源、重定位等数据目录项的RVA(相对虚拟地址)和大小。IMAGE_DATA_DIRECTORY结构体的定义如下:

1 typedef struct _IMAGE_DATA_DIRECTORY {
2     DWORD   VirtualAddress;
3     DWORD   Size;
4 } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

成员说明:

VirtualAddress:该目录项的相对虚拟地址的起始值。

Size:目录项的长度。
数据目录中的成员在数据中的索引如下定义所示:

#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory
//      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7   // (X86 usage)
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor

在数据目录中,并不是所有的目录项都会有值很多目录项的值都为0。因为很多目录项的值为0,所以说数据目录项是可选的。

IMAGE_SECTION_HEADER

节表的位置在IMAGE_OPTIONAL_HEADER(可选头)后面。节表中的每个IMAGE_SECTION_HEADER中都存放着可执行文件被映射到内存中所在位置的信

息,节的个数由IMAGE_FILE_HEADER中的NumberOfSections给出。这个值我们在前面读取过,它是06 00,也就是0x00000006,所以该文件有6个节表。

IMAGE_SECTION_HEADER的大小为40字节,所以节表总共占用240个字节。

所以节表的起始位置在0x00000200,终止位置在0x00000200 + 0x000000F0(240) -1 = 0x000002EF处。如下图所示
在这里插入图片描述
IMAGE_SECTION_HEADER结构体的定义如下

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

Name(8字节)

节表项的名称,节的名称用ASCII编码来保存。节名称的长度为IMAGE_SIZE_SHORT_NAME(8个字节),这是一个宏
如果字符串长度正好为 8 个字符,则没有终止字符。否则最后一个字符为终止字符。 对于较长的名称,此成员包含 (/) 的正斜杠,后跟十进制数的 ASCII 表示形式,该数字是字符串表中的偏移量。 可执行文件不使用字符串表,并且不支持长度超过 8 个字符的节名称。

我们这里第一个节表项前面8个字节的数据为2E 74 65 78 74 00 00 00,对应的字符为 “.text”
在这里插入图片描述
Misc

Misc是一个联合体,它有以下两个成员

Misc.PhysicalAddress

文件地址。

Misc.VirtualSize

加载到内存中的节的总大小(以字节为单位)。 如果此值大于 SizeOfRawData 成员,则节将填充零。

此字段仅对可执行文件有效,对于对象文件,应设置为 0。

SizeOfRawData:该值为数据实际的节表项大小。 此值必须是 IMAGE_OPTIONAL_HEADER 结构的 FileAlignment 成员的倍数。 如果此值小于 VirtualSize 成员,则部分的其余部分将填充零。 如果节仅包含未初始化的数据,则成员为零。

PointerToRawData:该节表项在磁盘文件上的偏移地址。此值必须是 IMAGE_OPTIONAL_HEADER 结构的 FileAlignment 成员的倍数。 如果节仅包含未初始化的数据,请将此成员设置为零。

PointerToRelocations

A file pointer to the beginning of the relocation entries for the section. If there are no relocations, this value is zero.

这里的翻译总感觉差点意思 ,直接贴MSDN上的英文原版。

PointerToLinenumbers

A file pointer to the beginning of the line-number entries for the section. If there are no COFF line numbers, this value is zero.

NumberOfRelocations

该节表项重定向的条数。如果是可执行文件,该值应该设置为0

NumberOfLinenumbers

The number of line-number entries for the section.

Characteristics

节表项的属性,定义了以下值:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

参考链接

  • https://www.cnblogs.com/zhaotianff/p/18186676

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

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

相关文章

HarmonyOS开发实战( Beta5版)应用性能工具CPU Profiler的使用规范

简介 本文档介绍应用性能分析工具CPU Profiler的使用方法,该工具为开发者提供性能采样分析手段,可在不插桩情况下获取调用栈上各层函数的执行时间,并展示在时间轴上。 开发者可通过该工具查看TS/JS代码及NAPI代码执行过程中的时序及耗时情况…

Web-gpt

AJAX AJAX(Asynchronous JavaScript and XML,异步JavaScript和XML)是一种用于创建动态网页应用的技术。它允许网页在不重新加载整个页面的情况下,异步地从服务器请求数据,并将这些数据更新到网页上。这提高了用户体验…

HarmonyOS开发实战( Beta5版)小程序场景性能优化开发指导

简介 小程序是一种轻量级的应用,它不需要下载、安装即可使用,用户可以通过扫描二维码或者搜索直接打开使用。小程序运行在特定的平台上,平台提供了小程序的运行环境(运行容器)和一些基础服务(小程序API&am…

【C++ 第十八章】C++11 新增语法(2)

前情回顾: 【C11 新增语法(1):1~6 点】 C11出现与历史、花括号统一初始化、initializer_list初始化列表、 auto、decltype、nullptr、STL的一些新变化 本文会使用到自己模拟实现的 string 和 list 类,为了更好的观察各…

笔记整理—内核!启动!—uboot部分(2)

上文中,我们说到了使用uboot去启动kernel支持的几种方式以及压缩kernel的几种形式,本章节将要接着内核的启动说起。 上一章我们对uImage格式进行了初步的说明,并说这样的格式已经被废弃,但是依然保留了相应的代码。boot_get_kerne…

MATLAB生成mif文件

MATLAB代码 % 参数设置 N 4096; % 数据点数量 t linspace(0, 2*pi, N); % 时间向量 width 12; % 位宽% 正弦波 sine_wave 2.5 * sin(t) 2.5; % 幅度在0到5之间% 三角波 tri_wave 5 - abs(mod(t/(2*pi)*4, 2) - 1);% 方波 square_wave 2.5 * (square(t) 1); % 将范围调…

Hive Tutorial For Beginners

Hive Tutorial For Beginners 一、Hive历史(History of Hive) Facebook 在面对日益增长的大数据时,选择了 Hadoop 作为解决方案。 但问题在于,许多用户并不熟悉 Java 或其他编程语言,这使得使用 Hadoop 的 MapReduc…

代码随想录——回文子串(Leetcode 647)

题目链接 我的题解(双指针) 思路: 当然,以下是对您提供的代码的解释: class Solution {public int countSubstrings(String s) {// 初始化回文子字符串的数量int count 0;// 遍历字符串的每个字符,使用…

无人机之电池篇

无人机电池作为无人机的重要组成部分,其性能、使用、保养及选择都至关重要。以下是对无人机电池的综合介绍: 一、无人机电池的基本参数 电池容量:电池容量直接影响无人机的续航能力。大容量电池,如5000mAh的电池,能提…

无人机道通布局的讲究详解!!!

一、通道分配与功能对应 基本通道:无人机遥控器通常至少包含四个基本通道,分别对应无人机的上下(升降)、左右(副翼)、前后(俯仰)和旋转(方向舵)控制。这些通…

关于报错 SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“ 的可能原因

1. 絮絮叨叨 学习或工作中,如果需要从头建立日志打印体系,笔者通常直接照抄之前的博客:《Java maven工程配置slf4j》,直接粘贴、复制相关依赖除了上述博客提到的slf4j-api、logback-classic,也看到过slf4j-simple、lo…

区域生长算法详解与Python实现

图像分割是计算机视觉中一个重要的任务,区域生长算法是其中的一种常见方法。本文将详细介绍区域生长算法的原理,并通过Python代码实现,带你一步步理解它的实际应用。 1. 区域生长算法简介 区域生长算法是一种基于像素相似性进行图像分割的方…

2025款宋L EV全面升级加量不加价,仅18.98万元起

8月30日,2024成都车展正式开幕,备受期待的比亚迪王朝网B级先锋猎装SUV——2025款宋L EV正式上市,搭载“天神之眼”高阶智能驾驶辅助系统DiPilot 100,e平台3.0、CTB、云辇-C三大明星技术,并新增外观内饰配色。凭借智驾、…

【2024】Datawhale X 李宏毅苹果书 AI夏令营 Task2

本文是关于李宏毅苹果书”线性模型“学习内容的记录。 线性模型 线性模型(linear model):将输入的特征 x x x(或 x \bold{x} x)乘上权重 ω \omega ω(或 ω \bold{\omega} ω),再…

Python简易IDE工作界面制作

、 休闲一下,学习编程还是要学习一些界面编程,能够根据需要制作图形操作界面,这样我们开发的程序才能方便操作和使用,同时获得更友好的人机交互体验。下面是一个用PyQt5制作的简易界面,供大学参考。如下图所示&a…

罪人的终幕(原题)

题目背景 而我承诺你,一切都将在一场盛大的,如同戏剧般的审判中结束…… 小小地旋转,轻轻地跳跃,然后便是「罪人」的谢幕。 题目描述 定义函数 𝑎(𝑥)a(x) 表示自然数 𝑥x 的不同的质因子的和。…

数据增强在Sentence Transformers中的作用:提高句子评分任务的性能

Sentence Transformers 是一个强大的 Python 库,它基于 Transformer 模型架构,如 BERT、RoBERTa 和 XLM-RoBERTa 等,用于学习和操作句子级别的向量表示。这个库特别适合于处理自然语言处理(NLP)任务,能够为…

实用好软-----电脑端 开源的视频无损剪切与合并工具

这个是一个开源项目LosslessCut 无损剪切就是基于关键帧的剪切,不需要重编码,因此速度非常快, 缺点就是切割时间无法达到非常精确,可能前后会有几秒的差距, 要做到精确的剪切,只能重编码。 LosslessCut在切…

学习之SQL语句之DQL(数据库查询语言)

DQL英文全称是Data Query Language(数据查询语言),数据查询语言,用来查询数据库中表的记录 查询关键字:SELECT 数据准备: CREATE TABLE emp ( id INT COMMENT “编号”, workno VARCHAR ( 10 ) COMMENT “工号”, NAME VARCHAR ( 10 ) COMME…

windows配置hadoop环境

目录 一、windows配置hadoop环境1、下载文件2、解压3、移动winutils.exe4、移动hadoop.dll5、配置代码内容 一、windows配置hadoop环境 1、下载文件 首先下载所需要的文件内容 共有三个文件,可以通过 这个链接 获得 2、解压 使用解压工具将 hadoop-3.0.0.tar.gz…