5

実行中のプログラムに含まれるメモリ マップ領域を確認するために、/proc/self/maps からデータを読み取る単純な C プログラムを作成します。

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
    char buf[1024];
    int fd;
    ssize_t n;

    fd = open("/proc/self/maps", O_RDONLY);
    if (fd < 0) {
        perror("");
    }
    while ((n = read(fd, buf, 1000)) > 0) {
        buf[n] = 0;
        printf("%s", buf);
    }
    close(fd);

    return 0;
}

プログラムの出力は次のようになります (ラベル付き)。

1. 08048000-08049000 r-xp 00000000 08:01 2323014    /tmp/a.out
2. 08049000-0804a000 rw-p 00000000 08:01 2323014    /tmp/a.out
3. b7f69000-b7f6a000 rw-p b7f69000 00:00 0
4. b7f6a000-b80c6000 r-xp 00000000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
5. b80c6000-b80c7000 ---p 0015c000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
6. b80c7000-b80c9000 r--p 0015c000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
7. b80c9000-b80ca000 rw-p 0015e000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
8. b80ca000-b80cd000 rw-p b80ca000 00:00 0
9. b80dd000-b80df000 rw-p b80dd000 00:00 0
10.b80df000-b80e0000 r-xp b80df000 00:00 0          [vdso]
11.b80e0000-b80fc000 r-xp 00000000 08:01 1826830    /lib/ld-2.9.so
12.b80fc000-b80fd000 r--p 0001b000 08:01 1826830    /lib/ld-2.9.so
13.b80fd000-b80fe000 rw-p 0001c000 08:01 1826830    /lib/ld-2.9.so
14.bfee9000-bfefe000 rw-p bffeb000 00:00 0          [stack]

実行ビットと書き込み可能ビットから推測できるように、最初の 2 行はそれぞれプログラムのコード セグメントとデータ セグメントに関連付けられています。

しかし、私を混乱させているのは、libc.so のことです。libc.so からマップされた領域があります。そのうちの 1 つはプライベート ビットしかなく、書き込み、読み取り、または実行できません。もう 1 つの興味深い点は、ld.so には 3 つのセグメントしかないことです。libc.so のセグメントと比較すると、プライベート ビットのみがオンになっているセグメントが欠落しています。

では、4 つのセグメントが実際に何をしているのか知りたいのですが。カーネル 2.6.28、gcc 3.4.6、および binutils 2.19 で Ubuntu SMP を使用しています。

4

1 に答える 1

7

、およびマッピングは、異なる権限が必要な単なる領域ですr-xpr--prw-p

ミステリー---pマッピングは、ELF ファイルによって記述されたセクションの仮想メモリ オフセットが、ファイル内の物理オフセットと必ずしも一致しない (アラインメントの理由でパディングがある場合がある) ことの結果です。

つまり、ELF ファイル自体は次のようになります。

| .... sections .... | .... more sections .... |

...しかし、次のようなメモリ レイアウトについて説明します。

| .... sections .... |     gap     | .... more sections .... |

(これはobjdump -hまたはを使用して表示できますreadelf -e。)

したがって、一般的な原則は、ld.soすべてに十分なメモリを割り当てる必要があるということです。

|                                                            |

...次に、最初の部分に 1 つのマッピングを作成します。

| .... sections .... |                                       |

...そして、2 番目のマッピングを作成して、2 番目の部分を適切な場所に配置します。

| .... sections .... |             | .... more sections .... |

次に、仮想アドレス空間に残された「穴」を保護します。これがミステリー マッピングです。

| .... sections .... |XXXXXXXXXXXXX| .... more sections .... |

物事を単純にするために、穴は再利用のために解放されるのではなく、保護されていると思います。これにより、各ライブラリが単一の仮想アドレス範囲のみを持ち、それがそれに属し、他の誰にも属さないことが保証されます。

于 2010-01-21T02:10:19.403 に答える