有两种用法madvise
with MADV_DONTNEED
现在在 glibc 中:
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);
有https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc由 Ulrich Drepper 于 2007 年 12 月 16 日提交(glibc 2.9 及更高版本的一部分):
- malloc/malloc.c (public_mTRIm):迭代所有 arenas 并调用
mTRIm 适合所有人。
(mTRIm):另外迭代所有空闲块并使用 madvise
为所有包含至少一个的块释放内存
内存页。
mTRIm
(now mtrim) 实施已更改。块中未使用的部分、按页面大小对齐且大小大于页面的部分可以标记为MADV_DONTNEED
:
/* 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);
的手册页malloc_trim
有没有:https://github.com/mkerrisk/man-pages/blob/master/man3/malloc_trim.3这是 kerrisk 在 2012 年做出的承诺:https://github.com/mkerrisk/man-pages/commit/a15b0e60b297e29c825b7417582a33e6ca26bf65
如我所能grep glibc 的 git,glibc 中没有手册页,并且没有提交 malloc_trim 联机帮助页来记录此补丁。 glibc malloc 最好也是唯一的文档是它的源代码:https://sourceware.org/git/?p=glibc.git;a=blob;f=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
从块的中间释放没有记录为 malloc/malloc.c 中的文本(并且malloc_trim
Commend 中的描述在 2007 年没有更新)并且没有记录在手册页项目中。 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)。
您可以再次询问 Drepper 和其他 glibc 开发人员,就像您在https://sourceware.org/ml/libc-help/2015-02/msg00022.html“malloc_trim() 行为”,但他们仍然没有回复。 (只有其他用户的错误答案,例如https://sourceware.org/ml/libc-help/2015-05/msg00007.html https://sourceware.org/ml/libc-help/2015-05/msg00008.html)
或者您可以测试malloc_trim
用这个简单的 C 程序(test_malloc_trim.c
) and 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);
printf("1:%p 2:%p 3:%p 4:%p\n", m1, m2, m3, m4);
free(m2);
malloc_trim(0); // 20000, 2000000
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
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0x7ffffafbfff0) = 0
brk(0xceb000) = 0xceb000
所以,有madvise
with MADV_DONTNEED
之后的 9 页malloc_trim(0)
当堆中间有 40008 字节的空洞时调用。