如何将 malloc 与 madvise 一起使用并启用 MADV_DONTDUMP 选项
How to use malloc with madvise and enable MADV_DONTDUMP option
我想使用 madvise
和 malloc
,但我总是遇到同样的错误:
madvise error: Invalid argument
我尝试使用 MADV_DONTDUMP
在我的二进制文件中保存一些 space 但它没有用。
页面大小为 4096。
int main(int argc, char *argv[])
{
void *p_optimize_object;
unsigned int optimize_object_size = 4096*256;
optimize_object_size = ((optimize_object_size / 4096) + 1) * 4096;
printf("optimize_object_size = %d\n", optimize_object_size);
p_optimize_object = malloc(optimize_object_size);
if (madvise(p_optimize_object, optimize_object_size, MADV_DONTDUMP | MADV_SEQUENTIAL) == -1)
{
perror("madvise error");
}
printf("OK\n");
return 0;
}
命令如下:
$ gcc -g -O3 madvice.c && ./a.out
输出:
madvise error: Invalid argument
你不能,即使你可以在某些情况下使用某些标志(并且你在这里尝试使用的标志应该相对无害),你也不应该这样做。 madvise
从比 malloc
给你的更低级别分配的内存上操作,并且从 malloc 弄乱内存可能会破坏 malloc。
如果你想要一些可以调用 madvise
的内存块,你应该使用 mmap
获得它。
你对sizeof
的用法是错误的;您仅分配了四个字节的内存(sizeof unsigned int),并为同一块内存调用了大小参数为 1M 的 madvise()。
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
void *p_optimize_object;
unsigned int optimize_object_size = 4096*256;
optimize_object_size = ((optimize_object_size / 4096) + 1) * 4096;
printf("optimize_object_size = %d\n", optimize_object_size);
p_optimize_object = malloc(sizeof(optimize_object_size));
fprintf(stderr, "Allocated %zu bytes\n", sizeof(optimize_object_size));
if (madvise(p_optimize_object, optimize_object_size, MADV_WILLNEED | MADV_SEQUENTIAL) == -1)
{
perror("madvise error");
}
printf("OK\n");
return 0;
}
输出:
optimize_object_size = 1052672
Allocated 4 bytes
madvise error: Invalid argument
OK
更新:
另一个问题是 malloc() 可以为您提供非对齐内存(可能对齐 4,8,16,...),而 madvice() 需要页面对齐内存:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
void *p_optimize_object;
unsigned int optimize_object_size = 4096*256;
int rc;
optimize_object_size = ((optimize_object_size / 4096) + 1) * 4096;
printf("optimize_object_size = %d\n", optimize_object_size);
#if 0
p_optimize_object = malloc(sizeof(optimize_object_size));
fprintf(stderr, "Allocated %zu bytes\n", sizeof(optimize_object_size));
#elif 0
p_optimize_object = malloc(optimize_object_size);
fprintf(stderr, "Allocated %zu bytes\n", optimize_object_size);
#else
rc = posix_memalign (&p_optimize_object, 4096, optimize_object_size);
fprintf(stderr, "Allocated %zu bytes:%d\n", optimize_object_size, rc);
#endif
// if (madvise(p_optimize_object, optimize_object_size, MADV_WILLNEED | MADV_SEQUENTIAL) == -1)
if (madvise(p_optimize_object, optimize_object_size, MADV_WILLNEED | MADV_DONTFORK) == -1)
{
perror("madvise error");
}
printf("OK\n");
return 0;
}
输出:
$ ./a.out
optimize_object_size = 1052672
Allocated 1052672 bytes:0
OK
对齐要求似乎是 linux 特定的:
Linux Notes
The current Linux implementation (2.4.0) views this system call more as a command than as advice and hence may return an error when it cannot
do what it usually would do in response to this advice. (See the ERRORS description above.) This is non-standard behavior.
The Linux implementation requires that the address addr be page-aligned, and allows length to be zero. If there are some parts of the speci‐
fied address range that are not mapped, the Linux version of madvise() ignores them and applies the call to the rest (but returns ENOMEM from
the system call, as it should).
最后:
I tried to use the MADV_DONTDUMP to save some space in my binaries but it didn't work.
这当然没有意义。 Malloc 或 posix_memalign 添加到您的地址 space,使(至少)您的 运行 程序的 VSIZ 更大。 this space 会发生什么完全掌握在(内核)内存管理器的手中,由您的程序对特定内存的引用驱动,maybe 来自 madvice 的一些提示.
I tried to use the MADV_DONTDUMP
to save some space in my binaries but it didn't work.
再次仔细阅读 madvise(2) man
页面。
地址应该是页对齐的。 malloc
的结果一般不是page aligned(page size往往是4Kbytes,但是看sysconf(3) for SC_PAGESIZE
). Use mmap(2) to ask for a page-aligned segment in your virtual address space.
您不会在二进制 executable. You'll just save space in your core dump, see core(5). And core dumps should not happen. See signal(7) (read also about segmentation fault and undefined behaviour) 中保存任何 space。
要禁用核心转储,请考虑 setrlimit(2) with RLIMIT_CORE
(or the ulimit -c
bash builtin 在您的终端 运行 a bash
shell).
我想使用 madvise
和 malloc
,但我总是遇到同样的错误:
madvise error: Invalid argument
我尝试使用 MADV_DONTDUMP
在我的二进制文件中保存一些 space 但它没有用。
页面大小为 4096。
int main(int argc, char *argv[])
{
void *p_optimize_object;
unsigned int optimize_object_size = 4096*256;
optimize_object_size = ((optimize_object_size / 4096) + 1) * 4096;
printf("optimize_object_size = %d\n", optimize_object_size);
p_optimize_object = malloc(optimize_object_size);
if (madvise(p_optimize_object, optimize_object_size, MADV_DONTDUMP | MADV_SEQUENTIAL) == -1)
{
perror("madvise error");
}
printf("OK\n");
return 0;
}
命令如下:
$ gcc -g -O3 madvice.c && ./a.out
输出:
madvise error: Invalid argument
你不能,即使你可以在某些情况下使用某些标志(并且你在这里尝试使用的标志应该相对无害),你也不应该这样做。 madvise
从比 malloc
给你的更低级别分配的内存上操作,并且从 malloc 弄乱内存可能会破坏 malloc。
如果你想要一些可以调用 madvise
的内存块,你应该使用 mmap
获得它。
你对sizeof
的用法是错误的;您仅分配了四个字节的内存(sizeof unsigned int),并为同一块内存调用了大小参数为 1M 的 madvise()。
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
void *p_optimize_object;
unsigned int optimize_object_size = 4096*256;
optimize_object_size = ((optimize_object_size / 4096) + 1) * 4096;
printf("optimize_object_size = %d\n", optimize_object_size);
p_optimize_object = malloc(sizeof(optimize_object_size));
fprintf(stderr, "Allocated %zu bytes\n", sizeof(optimize_object_size));
if (madvise(p_optimize_object, optimize_object_size, MADV_WILLNEED | MADV_SEQUENTIAL) == -1)
{
perror("madvise error");
}
printf("OK\n");
return 0;
}
输出:
optimize_object_size = 1052672
Allocated 4 bytes
madvise error: Invalid argument
OK
更新:
另一个问题是 malloc() 可以为您提供非对齐内存(可能对齐 4,8,16,...),而 madvice() 需要页面对齐内存:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
void *p_optimize_object;
unsigned int optimize_object_size = 4096*256;
int rc;
optimize_object_size = ((optimize_object_size / 4096) + 1) * 4096;
printf("optimize_object_size = %d\n", optimize_object_size);
#if 0
p_optimize_object = malloc(sizeof(optimize_object_size));
fprintf(stderr, "Allocated %zu bytes\n", sizeof(optimize_object_size));
#elif 0
p_optimize_object = malloc(optimize_object_size);
fprintf(stderr, "Allocated %zu bytes\n", optimize_object_size);
#else
rc = posix_memalign (&p_optimize_object, 4096, optimize_object_size);
fprintf(stderr, "Allocated %zu bytes:%d\n", optimize_object_size, rc);
#endif
// if (madvise(p_optimize_object, optimize_object_size, MADV_WILLNEED | MADV_SEQUENTIAL) == -1)
if (madvise(p_optimize_object, optimize_object_size, MADV_WILLNEED | MADV_DONTFORK) == -1)
{
perror("madvise error");
}
printf("OK\n");
return 0;
}
输出:
$ ./a.out
optimize_object_size = 1052672
Allocated 1052672 bytes:0
OK
对齐要求似乎是 linux 特定的:
Linux Notes The current Linux implementation (2.4.0) views this system call more as a command than as advice and hence may return an error when it cannot do what it usually would do in response to this advice. (See the ERRORS description above.) This is non-standard behavior.
The Linux implementation requires that the address addr be page-aligned, and allows length to be zero. If there are some parts of the speci‐ fied address range that are not mapped, the Linux version of madvise() ignores them and applies the call to the rest (but returns ENOMEM from the system call, as it should).
最后:
I tried to use the MADV_DONTDUMP to save some space in my binaries but it didn't work.
这当然没有意义。 Malloc 或 posix_memalign 添加到您的地址 space,使(至少)您的 运行 程序的 VSIZ 更大。 this space 会发生什么完全掌握在(内核)内存管理器的手中,由您的程序对特定内存的引用驱动,maybe 来自 madvice 的一些提示.
I tried to use the
MADV_DONTDUMP
to save some space in my binaries but it didn't work.
再次仔细阅读 madvise(2) man
页面。
地址应该是页对齐的。 malloc
的结果一般不是page aligned(page size往往是4Kbytes,但是看sysconf(3) for SC_PAGESIZE
). Use mmap(2) to ask for a page-aligned segment in your virtual address space.
您不会在二进制 executable. You'll just save space in your core dump, see core(5). And core dumps should not happen. See signal(7) (read also about segmentation fault and undefined behaviour) 中保存任何 space。
要禁用核心转储,请考虑 setrlimit(2) with RLIMIT_CORE
(or the ulimit -c
bash builtin 在您的终端 运行 a bash
shell).