gpt4 book ai didi

malloc - "malloc_trim(0)"到底是什么意思?

转载 作者:行者123 更新时间:2023-12-03 07:03:43 31 4
gpt4 key购买 nike

manual page告诉了我很多,通过它我了解了很多“glibc”内存管理的背景知识。

但是我还是很困惑。 “ma​​lloc_trim(0)”(注意零作为参数)是否意味着(1.)“堆”部分中的所有内存都将返回给操作系统?或者(2.)堆最顶部区域的所有“未使用”内存都将返回给操作系统?

如果答案是(1.),如果堆中仍在使用的内存怎么办?如果堆在某个地方使用了内存,它们是否会被消除,或者函数将无法成功执行?

如果答案是(2.),那么那些位于堆中而不是顶部的“漏洞”呢?它们不再是未使用的内存,但是堆的最顶层区域仍然被使用,这个调用会有效地工作吗?

谢谢。

最佳答案

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 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

从 block 的中间释放未记录为 malloc/malloc.c 中的文本,并且未记录在手册页项目中。 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 月有提交 https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc作者:Ulrich Drepper(它是 glibc 2.9 及更高版本的一部分),它更改了 mtrim 实现(但它没有更改任何文档或手册页,因为 glibc 中没有手册页):

  • malloc/malloc.c (public_mTRIm): Iterate over all arenas and call

mTRIm for all of them. (mTRIm): Additionally iterate over all free blocks and use madvise to free memory for all those blocks which contain at least one memory page.

block 中未使用的部分(任何位置,包括中间的 block )、按页面大小对齐且大小大于页面的部分可能会标记为 MADV_DONTNEED https://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);
}

这是现在 glibc 中 madviseMADV_DONTNEED 的两种用法之一,一种用于堆的顶部 (shr​​ink_heap),另一种用于堆的顶部部分 (shr​​ink_heap)正在标记任何 block (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

因此,在 malloc_trim(0) 调用之后,当内存中存在 40008 字节的漏洞时,出现了 madviseMADV_DONTNEED 的 9 个页面。堆的中间。

关于malloc - "malloc_trim(0)"到底是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15529643/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com