我想使用madvise
和malloc
,但我总是有相同的错误:
madvise错误:参数无效
我试图使用MADV_DONTDUMP
在二进制文件中节省一些空间,但没有成功。
页面大小为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 = %dn", 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("OKn");
return 0;
}
这是命令:
$ gcc -g -O3 madvice.c && ./a.out
输出:
madvise错误:参数无效
你不能,即使在某些情况下你可以用某些标志来做(你试图在这里使用的标志应该相对无害),你也不应该这样做。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 = %dn", optimize_object_size);
p_optimize_object = malloc(sizeof(optimize_object_size));
fprintf(stderr, "Allocated %zu bytesn", sizeof(optimize_object_size));
if (madvise(p_optimize_object, optimize_object_size, MADV_WILLNEED | MADV_SEQUENTIAL) == -1)
{
perror("madvise error");
}
printf("OKn");
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 = %dn", optimize_object_size);
#if 0
p_optimize_object = malloc(sizeof(optimize_object_size));
fprintf(stderr, "Allocated %zu bytesn", sizeof(optimize_object_size));
#elif 0
p_optimize_object = malloc(optimize_object_size);
fprintf(stderr, "Allocated %zu bytesn", optimize_object_size);
#else
rc = posix_memalign (&p_optimize_object, 4096, optimize_object_size);
fprintf(stderr, "Allocated %zu bytes:%dn", 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("OKn");
return 0;
}
输出:
$ ./a.out
optimize_object_size = 1052672
Allocated 1052672 bytes:0
OK
并且对齐要求似乎是特定于linux的:
Linux说明当前的Linux实现(2.4.0)将此系统调用更多地视为命令而非建议,因此当它不能返回时可能会返回错误按照这个建议做它通常会做的事。(请参阅上面的ERRORS描述。)这是非标准行为。
Linux实现要求地址addr与页面对齐,并允许长度为零。如果存在特定的某些部分Linux版本的madvise()忽略了未映射的指定地址范围,并将调用应用于其余地址范围(但从系统调用)。
最后:
我试图使用MADV_DONTDUMP来节省二进制文件中的一些空间,但没有成功。
当然,这没有意义。Malloc或posix_meagn添加到您的地址空间,使(至少)运行程序的VSIZ更大。这个空间发生的事情完全掌握在(内核)内存管理器手中,由程序对特定内存的引用驱动,可能有一些来自madvice的提示。
我试图使用
MADV_DONTDUMP
来在二进制文件中节省一些空间,但没有成功。
再次仔细阅读madvise(2)man
页面。
地址应与页面对齐。malloc
的结果通常不是页面对齐的(页面大小通常为4K字节,但请参阅sysconf(3)了解SC_PAGESIZE
)。使用mmap(2)在您的虚拟地址空间中请求页面对齐的段。
您不会在二进制可执行文件中节省任何空间。您只需在核心转储中节省空间,请参阅核心(5)。并且核心转储不应该发生。参见信号(7)(另请阅读有关分段故障和未定义行为的内容)。
要禁用核心转储,请考虑使用RLIMIT_CORE
(或运行bash
shell的终端中内置的ulimit -c
bash)设置rlimit(2)。