2013-03-20 323 views
5

manual page告訴我這麼多,通過它我知道很多關於「glibc」的內存管理的背景知識。「malloc_trim(0)」的真正含義是什麼?

但我仍然感到困惑。 「malloc_trim(0)」(注意零作爲參數)意思是(1.)「堆」部分中的所有內存都將返回到OS?或者(2.)堆的最頂部區域中的所有「未使用」內存都將返回到操作系統?

如果答案是(1.),如果堆中仍然使用了內存,該怎麼辦?如果堆在某處使用了momery,它們是否會被淘汰,或者該功能無法成功執行?

而如果答案是(2.),何談那些「」的地方,而不是在堆頂?他們不再是未使用的內存,但是堆的最上面的區域仍是使用,這種呼叫會有效地工作嗎?

謝謝。

回答

4

malloc_trim的手冊頁說它釋放空閒內存,所以如果在堆中分配了內存,它不會釋放整個堆。如果你知道你仍然需要一定量的內存,那麼這個參數就在那裏,所以釋放更多的內存會導致glibc以後不得不做不必要的工作。

至於漏洞,這是內存管理和將內存返回給操作系統的標準問題。該程序可用的主要低級堆管理是brksbrk,他們所能做的只是通過更改頂部來擴展或縮小堆區域。所以他們沒有辦法讓操作系統返回漏洞;一旦程序調用sbrk來分配更多的堆,那麼只有該空間的頂部是空閒的並且可以返回時才能返回該空間。

請注意,還有其他更復雜的方式來分配內存(例如匿名mmap),它可能與基於sbrk的分配有不同的約束。

malloc_trim
+0

現在有一種將堆中間的孔返回到操作系統的方法:MADV_DONTNEED(有時是MADV_FREE):http://code.metager.de/source/xref/gnu/glibc/malloc/malloc.c #4535'mtrim(mstate av,size_t pad)... __madvise(paligned_mem,size&〜psm1,MADV_DONTNEED);'。帶有這種標誌的「madvise」標誌着應用程序不需要頁面,OS可能會銷燬它們的數據並取消映射物理空間;下一次訪問頁面可能會生成頁面錯誤以將虛擬頁面重新映射到物理空間。 – osgx 2017-02-16 11:48:45

+0

代碼添加在https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc 68631c8eb92ff38d9da1ae34f6aa048539b199cc「(mTRIm):此外迭代所有空閒塊和使用madvise爲所有包含至少一個內存頁的塊釋放內存。「 - \t Ulrich Drepper 2007年12月16日(glibc 2.9) – osgx 2017-02-16 11:53:19

0

人頁面在這裏承諾:https://github.com/mkerrisk/man-pages/blob/master/man3/malloc_trim.3,並按照我的理解,它是由人的頁面項目的維護者從頭寫起,kerrisk 2012年:https://github.com/mkerrisk/man-pages/commit/a15b0e60b297e29c825b7417582a33e6ca26bf65

,我可以grep the glibc's git, there are no man pages in the glibc,並沒有承諾malloc_trim手冊頁記錄這個補丁。的glibc的malloc最好的和唯一的文檔是它的源代碼:https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c 有來自malloc/malloc.cmalloc_trim評論:

Additional functions: 
malloc_trim(size_t pad); 
609 /* 
610 malloc_trim(size_t pad); 
611 
612 If possible, gives memory back to the system (via negative 
613 arguments to sbrk) if there is unused memory at the `high' end of 
614 the malloc pool. You can call this after freeing large blocks of 
615 memory to potentially reduce the system-level memory requirements 
616 of a program. However, it cannot guarantee to reduce memory. Under 
617 some allocation patterns, some large free blocks of memory will be 
618 locked between two used chunks, so they cannot be given back to 
619 the system. 
620 
621 The `pad' argument to malloc_trim represents the amount of free 
622 trailing space to leave untrimmed. If this argument is zero, 
623 only the minimum amount of memory to maintain internal data 
624 structures will be left (one page or less). Non-zero arguments 
625 can be supplied to maintain enough trailing space to service 
626 future expected allocations without having to re-obtain memory 
627 from the system. 
628 
629 Malloc_trim returns 1 if it actually released any memory, else 0. 
630 On systems that do not support "negative sbrks", it will always 
631 return 0. 
632 */ 
633 int  __malloc_trim(size_t); 
634 

從塊中間釋放沒有記錄中的malloc文/ malloc.c並沒有記錄在man-pages項目中。 2012年的手冊頁可能是該函數的第一個手冊頁,不是由glibc的作者撰寫的。 glibc的信息頁只提​​到128 KB的M_TRIM_THRESHOLD: https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html#Malloc-Tunable-Parameters並且不列出malloc_trim函數https://www.gnu.org/software/libc/manual/html_node/Summary-of-Malloc.html#Summary-of-Malloc(並且它也不記錄memusage/memusagestat/libmemusage.so)。

2007年12月,由Ulrich Drepper提交了https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc(它是glibc 2的一部分)。9,並且改變mtrim實施新)(不過那是glibc無人頁)它並沒有改變任何文件或手冊頁:

  • 的malloc/malloc.c(public_mTRIm):遍歷所有競技場和電話

mTRIm所有這些。 (mTRIm):此外迭代所有空閒塊並使用madvise爲所有包含至少一個內存頁面的塊釋放內存。

塊的未使用的部分(任何地方,包括在中間塊),頁面大小對齊,並具有尺寸大於頁可被標記爲MADV_DONTNEEDhttps://sourceware.org/git/?p=glibc.git;a=blobdiff;f=malloc/malloc.c;h=c54c203cbf1f024e72493546221305b4fd5729b7;hp=1e716089a2b976d120c304ad75dd95c63737ad75;hb=68631c8eb92ff38d9da1ae34f6aa048539b199cc;hpb=52386be756e113f20502f181d780aecc38cbb66a

 INTERNAL_SIZE_T size = chunksize (p); 

     if (size > psm1 + sizeof (struct malloc_chunk)) 
     { 
      /* See whether the chunk contains at least one unused page. */ 
      char *paligned_mem = (char *) (((uintptr_t) p 
              + sizeof (struct malloc_chunk) 
              + psm1) & ~psm1); 

      assert ((char *) chunk2mem (p) + 4 * SIZE_SZ <= paligned_mem); 
      assert ((char *) p + size > paligned_mem); 

      /* This is the size we could potentially free. */ 
      size -= paligned_mem - (char *) p; 

      if (size > psm1) 
       madvise (paligned_mem, size & ~psm1, MADV_DONTNEED); 
     } 

這是總兩種用法之一的madvise與glibc的MADV_DONTNEED現在,一個用於(shrink_heap)的堆頂部部分和其他被標記的任何塊(mtrim)的:http://code.metager.de/source/search?q=MADV_DONTNEED&path=%2Fgnu%2Fglibc%2Fmalloc%2F&project=gnu

H A D arena.c 643 __madvise ((char *) h + new_size, diff, MADV_DONTNEED); 
H A D malloc.c 4535 __madvise (paligned_mem, size & ~psm1, MADV_DONTNEED); 

我們可以用這個簡單的C程序(test_malloc_trim.c)和strace/ltrace測試malloc_trim

#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <malloc.h> 

int main() 
{ 
    int *m1,*m2,*m3,*m4; 
    printf("%s\n","Test started"); 
    m1=(int*)malloc(20000); 
    m2=(int*)malloc(40000); 
    m3=(int*)malloc(80000); 
    m4=(int*)malloc(10000); 
    // check that all arrays are allocated on the heap and not with mmap 
    printf("1:%p 2:%p 3:%p 4:%p\n", m1, m2, m3, m4); 
    // free 40000 bytes in the middle 
    free(m2); 
    // call trim (same result with 2000 or 2000000 argument) 
    malloc_trim(0); 
    // call some syscall to find this point in the strace output 
    sleep(1); 
    free(m1); 
    free(m3); 
    free(m4); 
    // malloc_stats(); malloc_info(0, stdout); 
    return 0; 
} 

gcc test_malloc_trim.c -o test_malloc_trimstrace ./test_malloc_trim

write(1, "Test started\n", 13Test started 
)   = 13 
brk(0)         = 0xcca000 
brk(0xcef000)       = 0xcef000 
write(1, "1:0xcca010 2:0xccee40 3:0xcd8a90"..., 441:0xcca010 2:0xccee40 3:0xcd8a90 4:0xcec320 
) = 44 
madvise(0xccf000, 36864, MADV_DONTNEED) = 0 
... 
nanosleep({1, 0}, 0x7ffffafbfff0)  = 0 
brk(0xceb000)       = 0xceb000 

所以,有madviseMADV_DONTNEEDmalloc_trim(0)後9頁調用時,在堆的中間有40008個字節的空洞。

+0

GNU-like項目維護人員在手冊頁和其他文檔中的典型官方位置:https://sourceware.org/bugzilla/show_bug.cgi?id = 2531#c4「Ulrich Drepper 2006-05-01 man頁面不是用glibc維護的,告訴man頁面的維護者。「 – osgx 2017-02-16 13:06:55

相關問題