0

我需要找到一种使用 mmap 而不是 malloc 的方法。这怎么可能?(我不只使用 libc 系统调用)是的 brk() 是可能的。我使用了 sbrk() 但意识到它不是系统调用...(x86 内联汇编)

我一直在环顾四周,看到了这个:如何使用 mmap 在堆中分配内存?但这对我没有帮助,因为我有一个段错误。

基本上,我只想创建 3 块内存来存储字符。

说,

char * x = malloc(1000);
char * y = malloc(2000);
char * z = malloc(3000);

mmap 怎么可能,以后如何用 munmap 释放它?

4

2 回答 2

10

您是否仔细阅读了mmap(2)手册页?我建议多读几遍。

请注意,您只能要求内核 [thru mmapetc...] 管理与通常为 4096 字节的页面大小对齐的内存和倍数sysconf(_SC_PAGE_SIZE) (我假设在我的回答中)。

然后你可能会这样做:

  size_t page_size =  sysconf(_SC_PAGE_SIZE);
  assert (page_size == 4096); // otherwise this code is wrong

  // 1000 bytes fit into 1*4096
  char *x = mmap (NULL, page_size, PROT_READ|PROT_WRITE, 
                  MAP_ANONYMOUS, -1, (off_t)0);
  if (x == MMAP_FAILED) perror("mmap x"), exit (EXIT_FAILURE);

  // 2000 bytes fit into 1*4096
  char *y = mmap (NULL, page_size, PROT_READ|PROT_WRITE, 
                  MAP_ANONYMOUS, -1, (off_t)0);
  if (y == MMAP_FAILED) perror("mmap y"), exit (EXIT_FAILURE);

稍后释放内存,使用

  if (munmap(x, page_size))
     perror("munmap x"), exit(EXIT_FAILURE);

ETC

如果要分配 5Kbytes,则需要两页(因为 5Kbytes < 2*4096 和 5Kbytes > 1*4096)即mmap(NULL, 2*page_size,...

实际上,您所有的x, y,z仅占用 8000 个字节,并且可以放入两页而不是三页...但是您只能munmap将这些内存放在一起。

请注意,这mmap是一个可能非常昂贵的系统调用。malloc实现注意避免过于频繁地调用它,这就是为什么他们管理以前的free-d 区域以在以后(在进一步的malloc-s 中)重用它们而无需任何系统调用。在实践中,大多数malloc实现管理不同的大分配(例如超过一兆字节),这些分配通常是mmap-ed atmallocmunmap-ed at freetime.... 你可以研究一些malloc. 来自MUSL Libc的那个可能比 Glibc 更容易阅读malloc

顺便说一句,该文件/proc/1234/maps向您显示 pid 1234 进程的内存映射。也可以在终端中尝试cat /proc/self/maps,它显示该cat进程的内存映射。

于 2013-02-09T09:07:51.977 回答
4

您可以调用mmap以在 x86 asm 中进行匿名映射,例如:

    mov eax, 192    ; mmap
    xor ebx, ebx    ; addr   = NULL
    mov ecx, 4096   ; len    = 4096
    mov edx, $7     ; prot   = PROT_READ|PROT_WRITE|PROT_EXEC
    mov esi, $22    ; flags  = MAP_PRIVATE|MAP_ANONYMOUS
    mov edi, -1     ; fd     = -1 (Ignored for MAP_ANONYMOUS)
    xor ebp, ebp    ; offset = 0 (4096*0) (Ignored for MAP_ANONYMOUS)
    int $80         ; make call (There are other ways to do this too)
于 2013-02-09T09:39:58.350 回答