glibc Tcache机制

本文介绍了glibc 2.26引入的Tcache机制,用于提高内存分配效率。Tcache为每个线程预留64个bin,每个bin最多存储7个非Large Chunk的chunk。文章详细分析了Tcache的初始化、从Tcache获取和释放chunk的过程,以及在不同malloc和free场景下的工作原理。
摘要由CSDN通过智能技术生成

Tcache的简述

在Glibc的2.26中 新增了Tcache机制 这是ptmalloc2的缓存机制
Tcache在glibc中是默认开启的,在Tcache被开启的时候会定义如下东西

#if USE_TCACHE
/* We want 64 entries.  This is an arbitrary limit, which tunables can reduce.  */
# define TCACHE_MAX_BINS        64
# define MAX_TCACHE_SIZE    tidx2usize (TCACHE_MAX_BINS-1)

/* Only used to pre-fill the tunables.  */
# define tidx2usize(idx)    (((size_t) idx) * MALLOC_ALIGNMENT + MINSIZE - SIZE_SZ)

/* When "x" is from chunksize().  */
# define csize2tidx(x) (((x) - MINSIZE + MALLOC_ALIGNMENT - 1) / MALLOC_ALIGNMENT)
/* When "x" is a user-provided size.  */
# define usize2tidx(x) csize2tidx (request2size (x))

/* With rounding and alignment, the bins are...
   idx 0   bytes 0..24 (64-bit) or 0..12 (32-bit)
   idx 1   bytes 25..40 or 13..20
   idx 2   bytes 41..56 or 21..28
   etc.  */

/* This is another arbitrary limit, which tunables can change.  Each
   tcache bin will hold at most this number of chunks.  */
# define TCACHE_FILL_COUNT 7
#endif

Tcache为每个线程都预留了这样一个特殊的bins, bin的数量是64个 每个bin中最多缓存7个chunk。在64位系统上以0x10的字节递增,从24递增到1032字节。32位系统上则从12到512字节,所以Tcache缓存的是非Large Chunk的chunk

同时Tcache使用两个新的数据结构来管理Tcache中的bin

/* We overlay this structure on the user-data portion of a chunk when
   the chunk is stored in the per-thread cache.  */
typedef struct tcache_entry
{
   
  struct tcache_entry *next;
} tcache_entry;

/* There is one of these for each thread, which contains the
   per-thread cache (hence "tcache_perthread_struct").  Keeping
   overall size low is mildly important.  Note that COUNTS and ENTRIES
   are redundant (we could have just counted the linked list each
   time), this is for performance reasons.  */
typedef struct tcache_perthread_struct
{
   
  char counts[TCACHE_MAX_BINS];
  tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;

static __thread tcache_perthread_struct *tcache = NULL;

tcache_perthread_struct是为每个线程分配一个的总的bin的管理结构,有两个字段 一个字段counts记录对应Tcache的bin中现有的bin数量第二个字段entries用来具体指向相应bin中的chunk块 这个字段类似于fastbin的单链表结构来串连 因为只有一个next指针进行指向

选取一张来自CTF-WIKI的图来描述这种串连情况就是如下所示
tcache中chunk块的组织形式可以看到对应chunk的原本的fd域 在Tcache中就是tcache_entry的next域被填充为了指向下一个chunk的索引指针

Tcache的实现分析

Tcache的初始化

glibc中对Tcache

static void
tcache_init(void)
{
   
  mstate ar_ptr;
  void *victim = 0;
  const size_t bytes = sizeof (tcache_perthread_struct);	//获得malloc需要的字节数

  if (tcache_shutting_down)
    return;

  arena_get (ar_ptr, bytes);
  victim = _int_malloc (ar_ptr, bytes);//使用malloc为该结构分配内存
  if (!victim && ar_ptr != NULL)
    {
   
      ar_ptr = arena_get_retry (ar_ptr, bytes);
      victim = _int_malloc (ar_ptr, bytes);
    }


  if (ar_ptr != NULL)
    __libc_lock_unlock (ar_ptr->mutex);

  /* In a low memory situation, we may not be able to allocate memory
     - in which case, we just keep trying later.  However, we
     typically do this very early, so either there is sufficient
     memory, or there isn't enough memory to do non-trivi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值