2013-03-20 39 views
5

Các manual page nói với tôi rất nhiều và thông qua nó tôi biết rất nhiều kiến ​​thức cơ bản về quản lý bộ nhớ của "glibc"."malloc_trim (0)" thực sự có ý nghĩa gì?

Nhưng tôi vẫn bị nhầm lẫn. "malloc_trim (0)" (lưu ý 0 là tham số) có nghĩa là (1.) tất cả bộ nhớ trong phần "đống" sẽ được trả về hệ điều hành? Hoặc (2.) chỉ cần tất cả bộ nhớ "không sử dụng" của vùng cao nhất của heap sẽ được trả lại cho hệ điều hành?

Nếu câu trả lời là (1.), nếu bộ nhớ vẫn còn được sử dụng trong heap thì sao? nếu heap đã sử dụng momery ở một nơi nào đó, chúng sẽ bị loại bỏ hay hàm sẽ không thực thi thành công?

Trong khi nếu câu trả lời là (2.), những gì về những "lỗ" tại địa điểm chứ không phải là hàng đầu trong đống? Họ là bộ nhớ không sử dụng nữa, nhưng khu vực trên hầu hết các đống vẫn là được sử dụng, công việc gọi điện này có hiệu quả không?

Cảm ơn.

Trả lời

4

Trang hướng dẫn sử dụng cho malloc_trim cho biết nó giải phóng bộ nhớ trống, vì vậy nếu có bộ nhớ được cấp phát trong heap, nó sẽ không giải phóng toàn bộ đống. Các tham số có nếu bạn biết bạn vẫn sẽ cần một số tiền nhất định của bộ nhớ, do đó, giải phóng nhiều hơn mà sẽ gây ra glibc phải làm công việc không cần thiết sau này.

Đối với lỗ, đây là vấn đề tiêu chuẩn với quản lý bộ nhớ và trả bộ nhớ cho hệ điều hành. Quản lý heap cấp thấp chính có sẵn cho chương trình là brksbrk và tất cả những gì họ có thể làm là kéo dài hoặc thu nhỏ vùng heap bằng cách thay đổi phần trên cùng. Vì vậy, không có cách nào để họ trả lại lỗ hổng cho hệ điều hành; một khi chương trình đã gọi là sbrk để phân bổ nhiều heap hơn, không gian đó chỉ có thể được trả lại nếu phần trên cùng của không gian đó là miễn phí và có thể được trả lại.

Lưu ý rằng có nhiều cách khác, phức tạp hơn để cấp phát bộ nhớ (ví dụ: mmap ẩn danh), có thể có các ràng buộc khác với phân bổ dựa trên phân bổ sbrk.

+0

Hiện tại có phương pháp trả lại lỗ ở giữa vùng heap quay lại hệ điều hành: MADV_DONTNEED (và đôi khi là MADV_FREE): http://code.metager.de/source/xref/gnu/glibc/malloc/malloc.C# 4535 'mtrim (mstate av, size_t pad) ... __madvise (paligned_mem, kích thước & ~ psm1, MADV_DONTNEED);'. 'madvise' với những cờ như vậy đánh dấu các trang không cần thiết cho ứng dụng, hệ điều hành có thể phá hủy dữ liệu từ chúng và unmap không gian vật lý; truy cập tiếp theo vào trang có thể tạo ra pagefault để remap trang ảo vào không gian vật lý. – osgx

+0

Mã đã được thêm vào https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc 68631c8eb92ff38d9da1ae34f6aa048539b199cc "(mTRIm): Ngoài ra lặp qua tất cả các khối miễn phí và sử dụng madvise để giải phóng bộ nhớ cho tất cả các khối có chứa ít nhất một trang bộ nhớ. " - \t Ulrich Drepper Ngày 16 tháng 12 năm 2007 (glibc 2.9) – osgx

0
trang

Man of malloc_trim đã cam kết ở đây: https://github.com/mkerrisk/man-pages/blob/master/man3/malloc_trim.3 và như tôi hiểu, nó đã được viết bởi người đàn ông-trang dự án duy trì, kerrisk vào năm 2012 từ đầu: https://github.com/mkerrisk/man-pages/commit/a15b0e60b297e29c825b7417582a33e6ca26bf65

Như tôi có thể grep the glibc's git, there are no man pages in the glibc, và không có cam kết manpage malloc_trim để ghi lại bản vá này. Các tài liệu tốt nhất và duy nhất của malloc glibc là mã nguồn của nó: https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.cmalloc_trim ý kiến ​​từ malloc/malloc.c:

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 

Giải phóng từ giữa đoạn không ghi dưới dạng văn bản trong malloc/malloc.c và không được ghi lại trong dự án trang con người. Trang người dùng từ năm 2012 có thể là trang người đầu tiên của hàm, được viết không phải bởi tác giả của glibc. Trang thông tin của glibc chỉ đề cập đến M_TRIM_THRESHOLD là 128 KB: https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html#Malloc-Tunable-Parameters và không liệt kê hàm malloc_trim https://www.gnu.org/software/libc/manual/html_node/Summary-of-Malloc.html#Summary-of-Malloc (và nó cũng không ghi nhớ memusage/memusagestat/libmemusage.so).

Vào tháng 12 năm 2007 đã có cam kết https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc bởi Ulrich Drepper (nó là một phần của glibc 2.9 và mới hơn) mà thay đổi mtrim thực hiện (nhưng nó không thay đổi bất kỳ tài liệu hoặc trang người đàn ông như không có các trang người đàn ông trong glibc):

  • malloc/malloc.c (public_mTRIm): Lặp lại khắp nơi đấu trường và gọi

mTRIm cho tất cả chúng. (mTRIm): Ngoài ra lặp qua tất cả các khối miễn phí và sử dụng madvise để giải phóng bộ nhớ cho tất cả các khối có chứa ít nhất một trang bộ nhớ .

phần chưa sử dụng của khối (bất cứ nơi nào, bao gồm cả khối ở giữa), xếp trên kích thước trang và có kích thước hơn trang có thể được đánh dấu là 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); 
     } 

Đây là một trong tổng số hai tập quán của madvise với MADV_DONTNEED trong glibc bây giờ, một cho phần trên của đống (shrink_heap) và khác được đánh dấu của bất kỳ đoạn (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); 

Chúng tôi có thể kiểm tra malloc_trim với chương trình này đơn giản C (test_malloc_trim.c) và strace/ltrace:

#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_trim, strace ./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 

Vì vậy, đã có madvise với MADV_DONTNEED cho 9 trang sau malloc_trim(0) cuộc gọi, khi có lỗ 40008 byte ở giữa đống.

+0

Vị trí chính thức điển hình của người bảo trì dự án giống như GNU trên trang người đàn ông và tài liệu khác: https://sourceware.org/bugzilla/show_bug.cgi?id=2531#c4 "Ulrich Drepper 2006-05-01 Các trang người đàn ông không được duy trì bằng glibc. Hãy nói điều này với người bảo trì trang người đàn ông. " – osgx

Các vấn đề liên quan