hhuccpj 发表于 2015-01-21 21:49

smaps 内存分布

大虾们,晚上好~

我在分析一个程序内存波动的时候,抓取了/proc/pid/smaps数据
发现有一块64M左右的内存,其没有权限,但又是private
像下面这个样子
400df000-4048c000 ---p 00000000 00:00 0

请教下这段内存是用来干什么的?
为什么属于当前进程,当前进程又没有权限去rw呢?

实在不明白,,,

Tinnal 发表于 2015-01-22 08:21

这种段一般都是为了隔离其它的段,防止其它段越界访问的。

gaojl0728 发表于 2015-01-22 09:44

回复 1# hhuccpj


    64M? 是linux 64 bit? 那是glibc 给内存池分配的, 64位linux glibc 会给每个线程分配一个arena, 每个arena至少有1个64M的heap, 应该就是这个heap.

hhuccpj 发表于 2015-01-22 16:01

今天我发现这块会慢慢被修改为re-p,应该不是保护

hhuccpj 发表于 2015-01-22 16:06

今天我发现这块内存会满满被修改为rw-p。看起来像是先mmap,flag设置为空了,再然后慢慢mprotect修改。上午分析我也在想应该是内存池。我是64位的机子。但我内存明明是够的,为什么会触发再来一块呢?思考中,,,

gaojl0728 发表于 2015-01-22 16:23

回复 5# hhuccpj


    小伙很有前途啊, 观察问题很仔细, 从glibc代码来看, 的确是一开始映射的flags为0, 后来通过mprotect改成rw的
你如果用strace跟踪应该能抓到这个过程。

上代码:
static heap_info *
internal_function
#if __STD_C
new_heap(size_t size, size_t top_pad)
#else
new_heap(size, top_pad) size_t size, top_pad;
#endif
{
size_t page_mask = malloc_getpagesize - 1;
char *p1, *p2;
unsigned long ul;
heap_info *h;

if(size+top_pad < HEAP_MIN_SIZE)
    size = HEAP_MIN_SIZE;
else if(size+top_pad <= HEAP_MAX_SIZE)
    size += top_pad;
else if(size > HEAP_MAX_SIZE)
    return 0;
else
    size = HEAP_MAX_SIZE;
size = (size + page_mask) & ~page_mask;

/* A memory region aligned to a multiple of HEAP_MAX_SIZE is needed.
   No swap space needs to be reserved for the following large
   mapping (on Linux, this is the case for all non-writable mappings
   anyway). */
p2 = MAP_FAILED;
if(aligned_heap_area) {
    p2 = (char *)MMAP(aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE,
                      MAP_PRIVATE|MAP_NORESERVE);
    aligned_heap_area = NULL;
    if (p2 != MAP_FAILED && ((unsigned long)p2 & (HEAP_MAX_SIZE-1))) {
      munmap(p2, HEAP_MAX_SIZE);
      p2 = MAP_FAILED;
    }
}
if(p2 == MAP_FAILED) {
    p1 = (char *)MMAP(0, HEAP_MAX_SIZE<<1, PROT_NONE,
                      MAP_PRIVATE|MAP_NORESERVE);
    if(p1 != MAP_FAILED) {
      p2 = (char *)(((unsigned long)p1 + (HEAP_MAX_SIZE-1))
                  & ~(HEAP_MAX_SIZE-1));
      ul = p2 - p1;
      if (ul)
        munmap(p1, ul);
      else
        aligned_heap_area = p2 + HEAP_MAX_SIZE;
      munmap(p2 + HEAP_MAX_SIZE, HEAP_MAX_SIZE - ul);
    } else {
      /* Try to take the chance that an allocation of only HEAP_MAX_SIZE
       is already aligned. */
      p2 = (char *)MMAP(0, HEAP_MAX_SIZE, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE);
      if(p2 == MAP_FAILED)
        return 0;
      if((unsigned long)p2 & (HEAP_MAX_SIZE-1)) {
        munmap(p2, HEAP_MAX_SIZE);
        return 0;
      }
    }
}
if(mprotect(p2, size, PROT_READ|PROT_WRITE) != 0) {
    munmap(p2, HEAP_MAX_SIZE);
    return 0;
}
h = (heap_info *)p2;
h->size = size;
h->mprotect_size = size;
THREAD_STAT(stat_n_heaps++);
return h;
}

hhuccpj 发表于 2015-01-22 16:44

哈哈,谢谢夸奖,我怎么感觉有点飘的感觉,开个玩笑。我是想strace抓一下的,但这个问题只在高caps长时间下才发生,strace上去后性能上不去。我怀疑我用的下层平台有人改东西了,如大家所述的话,应该有动态加减线程数

gaojl0728 发表于 2015-01-22 16:52

回复 7# hhuccpj


有两种情况glibc会创建新的64M heap,
一种是新建线程如果在堆上分配内存会触发glibc分配, 另一种是老线程前面的64M heap用光了也会新分配新的,多个heap会穿成一个链表。

hhuccpj 发表于 2015-01-22 16:57

嗯,,我生日0729,比你晚一天,大哥在上,请受小弟一拜

gaojl0728 发表于 2015-01-22 17:31

回复 9# hhuccpj


    你哪年的,还不知道谁大呢。我84
页: [1] 2
查看完整版本: smaps 内存分布