2017-10-10 435 views
0

我期待使用madvisemalloc但我总是相同的错误:如何使用malloc用的madvise并启用MADV_DONTDUMP选项

madvise error: Invalid argument

我试图用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 = %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

+0

你知道'sizeof(optimize_object_size)'最可能等于4吗? – joop

+1

如果已经给出答案,请不要更正您的问题;这会使(否则是正确的)答案失效。 – joop

回答

1

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

UPDATE:

而另一个问题是,malloc()函数可以给你非ALIG斯内德内存(可能与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; 
} 

OUTPUT:


$ ./a.out 
optimize_object_size = 1052672 
Allocated 1052672 bytes:0 
OK 

并且alignement requerement似乎是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将添加到您的地址空间,从而使(至少)正在运行的程序的VSIZ变大。这个空间发生的事情完全掌握在(内核)内存管理器的手中,由程序对特定内存的引用驱动,也许是从madvice提供的一些提示。

+0

更正后感谢 – ruxob

+0

您不得在'malloc'或'posix_memalign'中使用'madvise'on内存。它似乎可以工作,但它不正确,迟早会破坏。当内存被释放并被malloc重新使用时,它很可能会破坏malloc内部和/或将来的分配。 – Art

+0

你从哪里读到的? linux手册页只提到地址空间:'在地址范围开始的地址addr中,长度为字节。“这让我感到惊讶,因为(低级别)内存管理在页面上执行 - >>页表表项。对于管理表中的条目,它们引用的内容无关紧要。 (只要它们不属于DMA等) – joop

1

你不能,甚至如果你能做到这一点在一定有特定标志的情况(以及你在这里尝试使用的标志应该是相对无害的),你不应该这样做。 madvise从低级别分配的内存操作比malloc给你和搞乱从malloc的内存将可能破坏malloc。

如果你想要一些可以调用madvise的内存块,你应该使用mmap来获得它。

0

I tried to use the MADV_DONTDUMP to save some space in my binaries but it didn't work.

再次阅读,并更仔细的madvise(2)man页面。

该地址应该页面对齐。 malloc的结果通常不是页面对齐的(页面大小通常为4K字节,但对于SC_PAGESIZE,请参阅sysconf(3))。使用mmap(2)要求您的virtual address space中的页面对齐段。

您不会在您的二进制文件executable中保存任何空间。您只需在核心转储中节省空间,请参阅core(5)核心转储不应该发生。请参阅signal(7)(还请阅读有关segmentation faultundefined behaviour)。

要禁用核心转储,而考虑用setrlimit(2)RLIMIT_CORE(或ulimit -cbash builtin在终端上运行的bash壳)。

相关问题