实现思路 沿着内存dump的步骤
small slab 先忽略tcache的话, 需要关注的结构 je_arenas
, arena
, bins
, bin->slabcur
bin->slabs_nofull
, bin->slabs_full
, je_bin_infos
extent_s
1 2 3 4 5 6 7 8 p je_arenas p (*(struct arena_s*)je_arenas[0]) p (*(struct arena_s*)je_arenas[0]).bins p (*(struct arena_s*)je_arenas[0]).bins[0] 0-NSIZES p je_bin_infos p (*(struct arena_s*)je_arenas[0]).bins[0].slabcur p *(struct extent_s*) [p (*(struct arena_s*)je_arenas[0]).bins[0].slabcur] #取slabcur 的slab p (*(struct arena_s*)je_arenas[0]).extents_dirty
extent 元信息中关于ind的信息?
extent_szind_get
(extent->e_bits & EXTENT_BITS_SZIND_MASK) >> EXTENT_BITS_SZIND_SHIFT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 EXTENT_BITS_ARENA_WIDTH = 12 ; EXTENT_BITS_ARENA_SHIFT =0 ; EXTENT_BITS_ARENA_MASK =((((1 << (12 )) - 1 )) << (0 )); EXTENT_BITS_SLAB_WIDTH =1 ; EXTENT_BITS_SLAB_SHIFT =(12 + 0 ); EXTENT_BITS_SLAB_MASK =((((1 << (1 )) - 1 )) << ((12 + 0 ))); EXTENT_BITS_COMMITTED_WIDTH = 1 ; EXTENT_BITS_COMMITTED_SHIFT = (1 + (12 + 0 )); EXTENT_BITS_COMMITTED_MASK =((((1 << (1 )) - 1 )) << ((1 + (12 + 0 )))); EXTENT_BITS_DUMPABLE_WIDTH = 1 ; EXTENT_BITS_DUMPABLE_SHIFT = (1 + (1 + (12 + 0 ))) ; EXTENT_BITS_DUMPABLE_MASK =((((1 << (1 )) - 1 )) << ((1 + (1 + (12 + 0 ))))); EXTENT_BITS_ZEROED_WIDTH =1 ; EXTENT_BITS_ZEROED_SHIFT =(1 + (1 + (1 + (12 + 0 )))); EXTENT_BITS_ZEROED_MASK = ((((1 << (1 )) - 1 )) << ((1 + (1 + (1 + (12 + 0 )))))); EXTENT_BITS_STATE_WIDTH = 2 ; EXTENT_BITS_STATE_SHIFT = (1 + (1 + (1 + (1 + (12 + 0 ))))); EXTENT_BITS_STATE_MASK =((((1 << (2 )) - 1 )) << ((1 + (1 + (1 + (1 + (12 + 0 ))))))); EXTENT_BITS_SZIND_WIDTH =8 ; EXTENT_BITS_SZIND_SHIFT =(2 + (1 + (1 + (1 + (1 + (12 + 0 )))))); EXTENT_BITS_SZIND_MASK =((((1 << (8 )) - 1 )) << ((2 + (1 + (1 + (1 + (1 + (12 + 0 )))))))); EXTENT_BITS_NFREE_WIDTH =((12 - 3 ) + 1 ); EXTENT_BITS_NFREE_SHIFT =(8 + (2 + (1 + (1 + (1 + (1 + (12 + 0 ))))))); EXTENT_BITS_NFREE_MASK =((((1 << (((12 - 3 ) + 1 ))) - 1 )) << ((8 + (2 + (1 + (1 + (1 + (1 + (12 + 0 ))))))))); EXTENT_BITS_SN_SHIFT =(((12 - 3 ) + 1 ) + (8 + (2 + (1 + (1 + (1 + (1 + (12 + 0 )))))))); EXTENT_BITS_SN_MASK =(18446744073709551615 << (((12 - 3 ) + 1 ) + (8 + (2 + (1 + (1 + (1 + (1 + (12 + 0 )))))))));
1 2 e_bits = 29863505920 11011110100000000001111000000000000
通过rtree 信息直接检索所有的extent
1 2 3 p je_extents_rtree.root #遍历R树 是一个1<<18 容量的数组, root是头指针 p je_extents_rtree.root[x].child # 每一个都是1个 1<<18容量的数组, child是头指针, 需要遍历非0x0的有效数 # 最后找出有效的叶子节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 struct rtree_leaf_elm_s { atomic_p_t le_bits; }; JEMALLOC_ALWAYS_INLINE extent_t * rtree_leaf_elm_bits_extent_get (uintptr_t bits) { uintptr_t high_bit_mask = ((uintptr_t )1 << LG_VADDR) - 1 = (1 << 48 ) - 1 ; uintptr_t low_bit_mask = ~(uintptr_t )1 ; uintptr_t mask = high_bit_mask & low_bit_mask; return (extent_t *)(bits & mask); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 eg: slab对应的base地址是 0x7a45207040 # 查看e_addr的地址为extent分配块的地址, 其中存放了各个region (gdb) p *(struct extent_s*)0x7a45207040 $7 = { e_bits = 29863505920 , e_addr = 0x7a45009000 , { e_size_esn = 4096 , e_bsize = 4096 }, ql_link = { qre_next = 0x7a45207040 , qre_prev = 0x7a45207040 }, ph_link = { phn_prev = 0x0 , phn_next = 0x0 , phn_lchild = 0x0 }, { e_slab_data = { bitmap = {2814749767106560 , 18446744073709551404 , 18446744073709551615 , 18446744073709551615 , 18446744073709551615 , 18446744073709551615 , 18446744073709551615 , 18446744073709551615 } }, e_prof_tctx = { repr = 0xa000000000000 } } } # rtree 第一级节点 0x7a45009000 >>30 Out[60 ]: 489 (gdb) p je_extents_rtree.root[489 ].child $23 = { repr = 0x7a44c000c0 } # rtree 第二级节点 In [62 ]: 0x7a45009000 >>12 & ((1 <<18 )-1 ) Out[62 ]: 20489 # 算相对 0x7a44c000c0 的偏移量 20489 *8 + 0x7a44c000c0 = 0x7a44c28108 # 查看 0x7a44c28108 的内容 (gdb) x/a 0x7a44c28108 0x7a44c28108 : 0x7a45207041 # 其index是0 0x7a45207041 >> 48 = 0