Debug调试原理(二)

调试器内部结构:

  符号管理模块:负责提供调试目标的调试符号。

读取二进制文件并解析其中调试符号,创建调试信息,打印变量等。

未避免启动时消耗大量时间和数据库中调试符号,不会一次性读取。,比如行号表和基准栈信息会在需要时生成。调试器刚开始只会扫描文件,快速定位文件基本信息,如作用域等。

  目标管理模块:

  处理被调试的进程:读写内存、检索调用栈等,内核中提供了ptrace,既允许一个进程查询和控制另一个进程的执行

ptrace:调试器基础 既-GDB 底层实现方式

    ptrace主要功能:<sys/ptrace.h>

  1. 追踪与分离:会收到SIGTRAP 或 SIGSTOP信号

  2. 读写内存地址空间内容

  3. 查询修改用户区域信息, info f

  4. 查询和修改被调试进程的信号信息和设置

  5. 设置时间触发器

  6. 控制进程运行:如从停止到恢复 ,或执行下一个指令

  7. 向被调试进程发信号,SIGKILL结束信号

分享一个比较好的博主写的,感兴趣可以了解下:https://baijiahao.baidu.com/s?id=1764499059583387145&wfr=spider&for=pc 

堆数据结构:

ptmalloc: <malloc/malloc.c>

        线程一旦创建栈大小就被固定,默认8MB

它的设计目标是提供高效的内存分配和释放操作,以满足多线程环境下的需求。

ptmalloc使用了多种技术来提高内存分配的性能和效率。其中包括:

  1. 内存池(盒子)配一块大内存作为内存池,然后根据需要将这块内存划分为小块进行分配。这样可以减少频繁的系统调用,提高内存分配的速度。

  2. 空闲链表:ptmalloc会维护一个链表来管理已经释放的内存块,以便下次分配时可以直接使用这些空闲的内存块,而不需要重新申请。

  3. 线程缓存:ptmalloc为每个线程维护了一个私有的内存缓存,用于快速分配小块内存。这样可以减少线程间的竞争,提高内存分配的并发性能。

ptmalloc中有四个字段

struct malloc_chunk{

   SIZE_T prev_size

   SIZE_T size

malloc_chunk *ft

malloc_chunk *bk

}

下面针对每一个字段进行分别说明:

 prev_size作用是:用于记录前一个空闲内存块的大小。它的目的是为让内存管理器可以由低端向合并地址高端的空闲块。当一个内存块被释放时,会检查前后相邻的内存块是否也是空闲的,如果前一个是空闲的,prev_size可以知道前一个内存块的大小,从而将两个空闲块合成一个更大的空闲块,减少碎片化提升利用率。

size的作用是:用来记录分配的内存块的大小的,通常以字节为单位表示。size字段的作用是帮助管理内存块的分配和释放。当调用malloc时会根据请求的大小在堆中找到一个合适大小的空闲的内存块,进行分配。在这个过程中,ptmalloc会使用size字段来记录这个内存块的大小。当我free的时候,ptmalloc会根据传入的指针找到对应的块,使用size来确定要释放的大小,这样ptmalloc就能将这个内存块标记为空闲状态,将其加入到空闲链表中。

fd和bk是分别标识当前块的前一个块和后一个块,可以在O(1)复杂度内找到前一个或后一个块

内存池(盒子):空闲块随数组索引增大而增大,间距是仔细选过的。

当收到用户请求,分配器检查并调整块的大小(会取整到不小于最小块大小),然后prev_size发挥作用。

TCMalloc:

  1. 线程缓存:为减少锁征用,为每个线程提供了本地缓存 我理解和C++中的thread_local类似,但是当线程释放内存时,会将内存给本地缓存,而非全局管理器

  2. 大小类:将内存分类,精确使用,减少内存碎片

  3. 页面堆:负责分配和回收大于一定阈值内存

  4. 内存释放:定期将线程本地缓存中空闲内存归还给内存管理器

  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值