0

mallocの代わりにmmapを使用する方法を見つける必要があります。これはどのように可能ですか?(私はlibcのみのsyscallを使用していません)そしてはいbrk()は可能です。sbrk()を使用しましたが、sys-callではないことに気付きました...(x86インラインアセンブリ)

私は周りを見回してこれを見てきました:mmapを使用してヒープにメモリを割り当てる方法は?しかし、セグメンテーション違反があったので、それは私には役に立ちませんでした。

基本的に、私がやりたいのは、文字を格納するための3つのメモリスラブを作成することだけです。

言う、

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

これはmmapでどのように可能であり、後でmunmapで解放する方法はありますか?

4

2 に答える 2

10

mmap(2)のマニュアルページを注意深く読みましたか?何度か読むことをお勧めします。

mmapカーネル[スルーなど...]に、ページサイズ(多くの場合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);

5Kバイトを割り当てる場合は、2ページが必要になります(5Kバイト<2*4096および5Kバイト>1* 4096のため)、つまりmmap(NULL, 2*page_size,...

実際には、すべての、、はx8000バイトしか使用せず、3ページではなく2ページに収まる可能性があります...しかし、その場合、一緒に使用できるのはそのメモリだけです。yzmunmap

mmapこれはシステムコールであり、非常に高額になる可能性があることに注意してください。malloc実装は、頻繁に呼び出さないように注意します。そのため、以前のfree-dゾーンを管理して、後で(さらにmalloc-sで)syscallなしで再利用します。実際には、ほとんどのmalloc実装は、異なる大きな割り当て(たとえば、メガバイト以上)を管理します。これは、多くの場合、一度にmmap-edmallocおよびmunmap-edにfreeなります。いくつかのソースコードを調べることができますmallocMUSL Libcのものは、Glibcよりも読みやすいかもしれませんmalloc

ところで、ファイル/proc/1234/mapsにはpid1234のプロセスのメモリマップが表示されています。cat /proc/self/mapsターミナルでも試してみてください。そのcatプロセスのメモリマップが表示されます。

于 2013-02-09T09:07:51.977 に答える
4

mmap次のようなものを使用して、x86asmで匿名マッピングを作成するために呼び出すことができます。

    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 に答える