Linux- DWARF调试文件格式
基本概念
DWARF是一个用于在可执行程序和其源代码之间进行关联的调试文件格式。当开发者使用调试编译选项(例如,使用gcc时的-g标志)编译程序时,编译器会生成这种格式的调试信息。这些信息在后续的调试过程中非常有用,例如,使用gdb(GNU调试器)。
以下是DWARF的一些主要特点和相关的详细信息:
-  历史: DWARF起初是为了满足UNIX系统上的高效、紧凑和跨平台的调试需求而设计的。自那时起,它已经经历了多个版本,每个版本都增加了新的特性。
-  版本:从 DWARF 1到DWARF 5,每个版本都引入了新的特性和改进,以支持新的编程语言特性、编译器优化等。
-  数据结构: DWARF信息由一系列的记录组成,这些记录描述了源代码的结构、变量、数据类型等。它们以所谓的"Debugging Information Entries" (DIEs)的形式存储。
-  查看工具:有一些工具可以查看和处理 DWARF调试信息。例如,readelf(与binutils套件一起提供)可以使用-wi选项来查看DWARF信息。
-  优势: - 跨平台:DWARF是一个可扩展的格式,可以支持多种不同的架构和操作系统。
- 紧凑:尽管包含大量的调试信息,但DWARF的设计使其尽可能紧凑,避免浪费存储空间。
- 灵活性:DWARF可以描述各种编程语言构造和复杂的数据类型。
 
- 跨平台:
-  与其他格式的比较:除了 DWARF,还有其他的调试格式,例如stabs和PE/COFF。但DWARF因其丰富的特性和跨平台支持而受到许多现代系统的青睐。
总之,DWARF是一个强大的调试信息格式,允许开发者在程序的执行过程中访问源代码级别的详细信息。对于开发者或者正在学习调试技术的读者来说,了解DWARF和如何使用它将非常有益。
示例
下面,我们用一个简单的C语言程序,展示它如何与DWARF调试信息交互。
假设我们有一个简单的C程序example.c:
#include <stdio.h>int add(int a, int b) {return a + b;
}int main() {int sum = add(5, 7);printf("The sum is: %d\n", sum);return 0;
}
我们使用GCC编译器编译这个程序,并使用-g选项来生成DWARF调试信息:
$ gcc -g -o example example.c
现在,可以使用readelf命令来查看生成的DWARF信息。例如,查看DWARF头部信息:
$ readelf --debug-dump=info example
这会列出关于源代码结构的很多信息,比如变量、函数等,并与其在源代码中的位置进行关联。
为了进一步调试程序,可以使用gdb:
$ gdb ./example
在GDB中,可以进行各种操作,如设置断点、查看变量值等。所有这些操作都是基于DWARF调试信息的。
例如,可以在add函数上设置断点:
(gdb) b add
然后运行程序:
(gdb) run
程序将在add函数处暂停执行,此时,可以查看和修改变量值、单步执行等。
总的来说,DWARF调试信息提供了程序的详细视图,使得像gdb这样的调试器可以与源代码进行交互。
DWARF调试信息
下面,我们来详细了解DWARF调试信息。
$ readelf --debug-dump=info exampleContents of the .debug_info section:Compilation Unit @ offset 0x0:Length:        0xf4 (32-bit)Version:       5Unit Type:     DW_UT_compile (1)Abbrev Offset: 0x0Pointer Size:  8<0><c>: Abbrev Number: 3 (DW_TAG_compile_unit)<d>   DW_AT_producer    : (indirect string, offset: 0x0): GNU C17 11.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection<11>   DW_AT_language    : 29       (C11)<12>   DW_AT_name        : (indirect line string, offset: 0x29): example.c<16>   DW_AT_comp_dir    : (indirect line string, offset: 0x0): /home/majn/python_project/socket_project<1a>   DW_AT_low_pc      : 0x1149<22>   DW_AT_high_pc     : 0x56<2a>   DW_AT_stmt_list   : 0x0<1><2e>: Abbrev Number: 1 (DW_TAG_base_type)<2f>   DW_AT_byte_size   : 8<30>   DW_AT_encoding    : 7        (unsigned)<31>   DW_AT_name        : (indirect string, offset: 0x8e): long unsigned int<1><35>: Abbrev Number: 1 (DW_TAG_base_type)<36>   DW_AT_byte_size   : 4<37>   DW_AT_encoding    : 7        (unsigned)<38>   DW_AT_name        : (indirect string, offset: 0x93): unsigned int<1><3c>: Abbrev Number: 1 (DW_TAG_base_type)<3d>   DW_AT_byte_size   : 1<3e>   DW_AT_encoding    : 8        (unsigned char)<3f>   DW_AT_name        : (indirect string, offset: 0xa0): unsigned char<1><43>: Abbrev Number: 1 (DW_TAG_base_type)<44>   DW_AT_byte_size   : 2<45>   DW_AT_encoding    : 7        (unsigned)<46>   DW_AT_name        : (indirect string, offset: 0xbc): short unsigned int<1><4a>: Abbrev Number: 1 (DW_TAG_base_type)<4b>   DW_AT_byte_size   : 1<4c>   DW_AT_encoding    : 6        (signed char)<4d>   DW_AT_name        : (indirect string, offset: 0xa2): signed char<1><51>: Abbrev Number: 1 (DW_TAG_base_type)<52>   DW_AT_byte_size   : 2<53>   DW_AT_encoding    : 5        (signed)<54>   DW_AT_name        : (indirect string, offset: 0xd6): short int<1><58>: Abbrev Number: 4 (DW_TAG_base_type)<59>   DW_AT_byte_size   : 4<5a>   DW_AT_encoding    : 5        (signed)<5b>   DW_AT_name        : int<1><5f>: Abbrev Number: 1 (DW_TAG_base_type)<60>   DW_AT_byte_size   : 8<61>   DW_AT_encoding    : 5        (signed)<62>   DW_AT_name        : (indirect string, offset: 0xb3): long int<1><66>: Abbrev Number: 1 (DW_TAG_base_type)<67>   DW_AT_byte_size   : 1<68>   DW_AT_encoding    : 6        (signed char)<69>   DW_AT_name        : (indirect string, offset: 0xa9): char<1><6d>: Abbrev Number: 5 (DW_TAG_const_type)<6e>   DW_AT_type        : <0x66><1><72>: Abbrev Number: 6 (DW_TAG_subprogram)<73>   DW_AT_external    : 1<73>   DW_AT_name        : (indirect string, offset: 0xcf): printf<77>   DW_AT_decl_file   : 2<78>   DW_AT_decl_line   : 356<7a>   DW_AT_decl_column : 12<7b>   DW_AT_prototyped  : 1<7b>   DW_AT_type        : <0x58><7f>   DW_AT_declaration : 1<7f>   DW_AT_sibling     : <0x8a><2><83>: Abbrev Number: 7 (DW_TAG_formal_parameter)<84>   DW_AT_type        : <0x8a><2><88>: Abbrev Number: 8 (DW_TAG_unspecified_parameters)<2><89>: Abbrev Number: 0<1><8a>: Abbrev Number: 9 (DW_TAG_pointer_type)<8b>   DW_AT_byte_size   : 8<8c>   DW_AT_type        : <0x6d><1><90>: Abbrev Number: 10 (DW_TAG_subprogram)<91>   DW_AT_external    : 1<91>   DW_AT_name        : (indirect string, offset: 0xae): main<95>   DW_AT_decl_file   : 1<96>   DW_AT_decl_line   : 7<97>   DW_AT_decl_column : 5<98>   DW_AT_type        : <0x58><9c>   DW_AT_low_pc      : 0x1161<a4>   DW_AT_high_pc     : 0x3e<ac>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)<ae>   DW_AT_call_all_tail_calls: 1<ae>   DW_AT_sibling     : <0xc2><2><b2>: Abbrev Number: 11 (DW_TAG_variable)<b3>   DW_AT_name        : sum<b7>   DW_AT_decl_file   : 1<b8>   DW_AT_decl_line   : 8<b9>   DW_AT_decl_column : 9<ba>   DW_AT_type        : <0x58><be>   DW_AT_location    : 2 byte block: 91 6c      (DW_OP_fbreg: -20)<2><c1>: Abbrev Number: 0<1><c2>: Abbrev Number: 12 (DW_TAG_subprogram)<c3>   DW_AT_external    : 1<c3>   DW_AT_name        : add<c7>   DW_AT_decl_file   : 1<c8>   DW_AT_decl_line   : 3<c9>   DW_AT_decl_column : 5<ca>   DW_AT_prototyped  : 1<ca>   DW_AT_type        : <0x58><ce>   DW_AT_low_pc      : 0x1149<d6>   DW_AT_high_pc     : 0x18<de>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)<e0>   DW_AT_call_all_calls: 1<2><e0>: Abbrev Number: 2 (DW_TAG_formal_parameter)<e1>   DW_AT_name        : a<e3>   DW_AT_decl_file   : 1<e3>   DW_AT_decl_line   : 3<e3>   DW_AT_decl_column : 13<e4>   DW_AT_type        : <0x58><e8>   DW_AT_location    : 2 byte block: 91 6c      (DW_OP_fbreg: -20)<2><eb>: Abbrev Number: 2 (DW_TAG_formal_parameter)<ec>   DW_AT_name        : b<ee>   DW_AT_decl_file   : 1<ee>   DW_AT_decl_line   : 3<ee>   DW_AT_decl_column : 20<ef>   DW_AT_type        : <0x58><f3>   DW_AT_location    : 2 byte block: 91 68      (DW_OP_fbreg: -24)<2><f6>: Abbrev Number: 0<1><f7>: Abbrev Number: 0
这是一个.debug_info节的内容,该节是由readelf从ELF文件中提取的。这个节包含了程序的DWARF调试信息。以下是这些输出信息的简要说明:
-  Compilation Unit: 表示源文件的一个编译单位。这里是 example.c。- DW_AT_producer: 编译器和其版本信息。
- DW_AT_language: 源代码的编程语言。
- DW_AT_name: 源文件名。
- DW_AT_comp_dir: 源文件的编译目录。
- DW_AT_low_pc 和 DW_AT_high_pc: 表示程序地址范围。
 
-  DW_TAG_base_type: 这是基础类型的定义,例如 unsigned int,unsigned char等。- DW_AT_byte_size: 数据类型的大小。
- DW_AT_encoding: 数据类型的编码,例如signed、unsigned等。
- DW_AT_name: 数据类型的名称。
 
-  DW_TAG_subprogram: 代表一个函数或子程序。 - DW_AT_external: 表明这个函数是否是外部的。
- DW_AT_name: 函数名。
- DW_AT_decl_file、DW_AT_decl_line、DW_AT_decl_column: 声明函数的文件、行号和列号。
- DW_AT_prototyped: 表明该函数是否有原型。
- DW_AT_type: 函数返回的数据类型。
 
-  DW_TAG_formal_parameter: 表示函数的一个形式参数。 - DW_AT_name: 参数名称。
- DW_AT_decl_file、DW_AT_decl_line、DW_AT_decl_column: 参数在源文件中的位置。
- DW_AT_type: 参数的数据类型。
- DW_AT_location: 参数在堆栈上的位置。
 
-  DW_TAG_pointer_type: 表示指针类型。 - DW_AT_byte_size: 指针的大小,通常为地址大小。
- DW_AT_type: 指针所指向的数据类型。
 
-  DW_TAG_const_type: 表示常量类型。 
-  DW_TAG_unspecified_parameters: 表示函数可能有不确定数量的参数。 
-  DW_TAG_variable: 表示一个变量。 - DW_AT_name: 变量名。
- DW_AT_type: 变量的数据类型。
- DW_AT_location: 变量的位置,可能是寄存器或堆栈上的位置。
 
上述内容只是一个粗略的说明,DWARF格式包含了大量的复杂信息,用于在不运行程序的情况下,对其进行详细的分析和调试。
在DWARF调试信息中,DW_AT_type: <0x58>表示一个引用或指针,它指向另一个DWARF条目。具体来说,这是一个偏移量,它从当前编译单元的开始处计算,指向描述该类型的DWARF条目。
在给定的输出中,DW_AT_type: <0x58>意味着该属性引用了偏移量为0x58的条目以获取其类型信息。
为了理解这代表什么,我们应该查找偏移量为0x58的条目。在提供的输出中,可以看到以下条目:
<1><58>: Abbrev Number: 4 (DW_TAG_base_type)<59>   DW_AT_byte_size   : 4<5a>   DW_AT_encoding    : 5        (signed)<5b>   DW_AT_name        : int
这意味着DW_AT_type: <0x58>引用的是一个基础类型,它是一个带符号的整数int,大小为4字节。
DW_AT_stmt_list
DW_AT_stmt_list 是一个属性,用于在DWARF调试信息中引用一个行号信息表的偏移量。这个属性关联了源代码的行号和生成的机器代码之间的映射,使得调试工具能够准确地确定执行的源代码行。
具体来说,当我们在调试器中设置断点或在运行时遇到错误时,DW_AT_stmt_list 使得调试器可以准确地显示源代码中的相关行。
值得注意的是,DW_AT_stmt_list 的值是一个偏移量,指向 .debug_line 节区中的一个位置,该位置包含与编译单元关联的行号程序。
这允许开发者和调试工具从机器代码位置回溯到源代码位置,从而可以进行更有效的调试。
Abbrev Number
Abbrev Number 在 DWARF 调试信息中是一个非常重要的概念,用于表示一个 “abbreviation” 的唯一标识符。它与一个特定的 “abbreviation” 对象关联,该对象定义了一个特定的 DIE(Debugging Information Entry)的结构和属性。简单地说,它是一个用于描述 DIE 结构的模板。
让我们详细解析一下:
-  DIE (Debugging Information Entry): 在 DWARF 中,调试信息由许多的 DIEs 组成。每个 DIE 描述了编译单位中的某个实体,如变量、类型、函数等。每个 DIE 都有一个 “tag”(如 DW_TAG_base_type),用于描述其表示的实体类型。
-  Abbreviations: 由于调试信息可能会很大,DWARF 使用一种缩写机制来减少所需的空间。这种机制通过定义一组 “abbreviations” 来工作,每个 “abbreviation” 描述了一种特定的 DIE 结构(包括其标签和属性)。这些 “abbreviations” 存储在 .debug_abbrev节区中。
-  Abbrev Number: 每个 “abbreviation” 都有一个唯一的编号,称为 Abbrev Number。这允许.debug_info节区中的 DIEs 通过简单地引用这个编号来描述其结构,而不是重复每个属性和标签。
因此,当我们在 .debug_info 节区中看到 Abbrev Number: 1,这意味着可以查找 .debug_abbrev 节区中的编号为 1 的 “abbreviation”,从而知道该 DIE 的结构和属性。
DW_AT_low_pc 和 DW_AT_high_pc
在DWARF调试信息中,DW_AT_low_pc 和 DW_AT_high_pc 是两个非常重要的属性,它们定义了一个代码范围的开始和结束地址。
-  DW_AT_low_pc: 这是代码段的起始地址。在上面给出的例子中, DW_AT_low_pc: 0x1149表示相关的代码段(可能是一个函数或其他代码块)从地址0x1149开始。
-  DW_AT_high_pc: 在早期的DWARF版本中,这是代码段的结束地址。但在后来的版本中(尤其是DWARF4之后),这的含义发生了变化,它代表与 DW_AT_low_pc的偏移量,而不是实际的结束地址。在上面给出的例子中,DW_AT_high_pc: 0x56很可能表示代码段的长度是0x56字节。因此,真正的结束地址将是0x1149 + 0x56。
为了确定 DW_AT_high_pc 的确切含义(是否是结束地址还是偏移量),需要查看DWARF版本以及可能存在的其他属性,如DW_AT_ranges。但在大多数情况下,考虑到新版本的DWARF,可以假设DW_AT_high_pc 表示从DW_AT_low_pc 的偏移量。
DW_AT_decl_file
在DWARF调试信息中,DW_AT_decl_file 属性表示源文件的索引,它指向文件名列表(通常存储在 .debug_line 节中的文件名表中)。
在上面的例子中,DW_AT_decl_file : 1 表示这个特定的实体(可能是一个变量、函数等)是在文件名列表中索引为1的文件中声明的。
为了找出索引1真正代表的文件名,需要查看 .debug_line 节,并找到对应的文件名表。这个表通常会列出编译单元中用到的所有文件,每个文件都有一个唯一的索引号,从1开始。这样,DWARF信息可以通过简单地引用索引号来指代一个特定的文件,而不是多次重复文件的完整路径名,从而节省空间。
相关文章:
Linux- DWARF调试文件格式
基本概念 DWARF是一个用于在可执行程序和其源代码之间进行关联的调试文件格式。当开发者使用调试编译选项(例如,使用gcc时的-g标志)编译程序时,编译器会生成这种格式的调试信息。这些信息在后续的调试过程中非常有用,…...
 
软件工程第六周
软件体系结构概述 体系结构:一种思想,而框架就是思想的实现,设计模式就是根据某一特殊问题实现的框架。 体系结构:体系结构是软件系统的高级结构。它定义了系统的主要组成部分,以及这些部分之间的关系和交互方式。 框…...
node+pm2安装部署
1、安装node 下载node安装包: wget https://nodejs.org/dist/v16.14.0/node-v16.14.0-linux-x64.tar.xz 解压: tar -xvJf node-v14.17.0-linux-x64.tar.xz 配置环境变量,在/etc/profile文件最后添加以下脚本: export PATH$P…...
大数据学习(11)-hive on mapreduce详解
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博>主哦&#x…...
 
MyBatis基础之自动映射、映射类型、文件注解双配置
文章目录 自动映射原理jdbcType同时启用配置文件和注解两种配置方式 自动映射原理 在 MyBatis 的配置文件(settings 元素部分)中,有一个 autoMappingBehavior 配置,其默认值为 PARTIAL ,表示 MyBatis 会自动映射&…...
 
8、docker 安装 nginx
1、下载镜像 docker pull nginx 2、本机创建目录 1)创建nginx挂载目录 mkdir /usr/local/nginx 2)进入nginx目录 cd /usr/local/nginx 3)创建 www和logs目录 mkdir -p www logs 3、创建nginx容器 此容器用于复制配置文件,复…...
 
关于Skywalking Agent customize-enhance-trace对应用复杂参数类型取值
对于Skywalking Agent customize-enhance-trace 大家应该不陌生了,主要支持以非入侵的方式按用户自定义的Span跟踪对应的应用方法,并获取数据。 参考https://skywalking.apache.org/docs/skywalking-java/v9.0.0/en/setup/service-agent/java-agent/cust…...
手机路径、Windows路径知识及delphiXE跨设备APP自动下载和升级
手机路径、Windows路径知识 及delphiXE跨设备APP自动下载和升级 一、APP安装程序文件版本和权限信息 1、运行时动态调用Android apk的AndroidManifest.xml获取versionName 2、运行时动态调用IOS ipa的info.plist获取CFBundleVersion (和entitlements)…...
 
GitLab 502问题解决方案
由于最近 gitlab 切换到另一台服务器上部署的 gitlab 后,经常出现 502。平时重启 gitlab 后都能解决,今天突然重启多次后都还是 502(重启日志是正常的),遂通过 gitlab-ctl tail 查看日志进行排查。 gitlab-ctl tail通…...
 
selenium打开火狐浏览器
项目上需求为:甲方OA 系统是IE系统,需要从IE系统点个按钮打开火狐浏览器单点登录跳转到我们的系统 前期解决方案为:打开浏览器就行了,然后就用的是打开本地浏览器,但是由于B/S架构,有别人远程访问我的ip来…...
 
多标签分类论文笔记 | ML-Decoder: Scalable and Versatile Classification Head
个人论文精读笔记,主要是翻译心得,欢迎旁观,如果有兴趣可以在评论区留言,我们一起探讨。 Paper: https://arxiv.org/pdf/2111.12933.pdf Code: https://github.com/Alibaba-MIIL/ML_Decoder 文章目录 0. 摘要1. 介绍2. 方法2.1 Ba…...
 
修改http_charfinder.py使能在python311环境中运行
需要修改两个函数,第一个是init函数,修改如下: async def init(loop, address, port): # <1> # app web.Application(looploop) # <2> # app.router.add_route(GET, /, home) # <3> app web.Application(…...
 
蓝桥杯(跳跃 C++)
思路: 1、根据题目很容易知道可以用深度搜索、广度搜索、动态规划的思想解题。 2、这里利用深度搜素,由题目可知,可以往九个方向走。 3、这里的判断边界就是走到终点。 #include<iostream> using namespace std; int max1 0; int …...
 
08 | Jackson 注解在实体里面如何应用?常见的死循环问题如何解决?
我们用 Spring Boot 里面默认集成的 fasterxml.jackson 加以说明,这看似和 JPA 没什么关系,但是一旦我们和 Entity 一起使用的时候,就会遇到一些问题,特别是新手同学,我们这一课时详细介绍一下用法。先来跟着我了解一下…...
JavaScript—获取当前时间 并转化为yyyy-MM-dd hh:mm:ss格式
JavaScript—获取当前时间 并转化为yyyy-MM-dd hh:mm:ss格式 每次项目都需要用到时间戳格式,可以封装成一个方法 下次直接CV过去 const timestampPadStart=(str)=>{str=String(str);return str.padStart(2,0)...
 
OpenHarmony创新赛丨报名倒计时,超强秘籍带你直通大奖!
OpenHarmony创新赛报名倒计时开始啦! 设于开放原子全球开源大赛下的OpenHarmony创新赛,目前正在如火如荼地进行赛事招募中!这次大赛围绕创新应用、商显行业、金融行业三大赛题,邀请来自企业、个人、高校师生等各界群体的优秀开发者…...
 
Linux高性能服务器编程 学习笔记 第十四章 进程池和线程池
动态创建子进程或子线程的缺点: 1.动态创建进程或线程比较耗时,这将导致较慢的客户响应。 2.动态创建的子进程或子线程通常只用来为一个客户服务(除非我们做特殊处理),这将导致系统上产生大量的进程或线程,…...
 
微信小程序/vue3/uview-plus form兜底校验
效果图 代码 <template><u-form :model"form" ref"formRole" :rules"rules"><u-form-item prop"nickname"><u-input v-model"form.nickname" placeholder"姓名" border"none" /&…...
 
Photoshop 2024正式发布!内置最新PS AI,创意填充等功能无限制使用!
PS正式版目前更新到了2024,版本为25.0。 安装教程 1、下载得到安装包后,先解压。鼠标右键,【解压到当前文件夹】 2、双击 Set-up 开始安装 3、这里可以更改安装位置。如果C盘空间不够大,可以把它安装到C盘以外。更改好后&#x…...
 
芯片学习记录TLP184
TLP184 芯片介绍 TLP184是一款光耦隔离器,它的主要特点包括:高电压耐受能力、高传输速度、高共模隔离能力、低功耗等。它可以用于工业自动化、通信设备、家用电器等领域的电气隔离应用。由一个光电晶体管组成,光学耦合到两个红外发射二极管…...
 
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
 
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
 
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
 
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
 
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
 
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
