【问题标题】:What's the memory before 0x08048000 used for in 32 bit machine?0x08048000 之前的内存用于 32 位机器是什么?
【发布时间】:2011-11-03 12:25:11
【问题描述】:

在 Linux 中,我了解到每个进程都在 32 位机器中存储从 0x08048000 开始的数据(在 64 位机器中从 0x00400000 开始)。

但我不知道从那里开始的原因。 0x08048000之前的内存是干什么用的?

更新: 有些人认为它是为内核映射的。不过据我所知,Linux内核使用的是用户栈之后的高端内存。

【问题讨论】:

    标签: linux memory process operating-system


    【解决方案1】:

    答案真的是:一堆东西。可执行文件的加载地址没有神奇的意义,几乎任何东西都可以映射到较低的地址。常见的例子包括:C 库(如 C 库)、动态加载器 ld.so 和内核 VDSO(内核映射的动态代码库,在 x86 Linux 中为内核提供一些接口)。但是你几乎可以使用 mmap() 系统调用映射任何你想要的东西。

    例如在我的特定机器上,地图如下(获得但“cat /proc/self/maps”):

    gby@watson:~$ cat /proc/self/maps 
    001c0000-00317000 r-xp 00000000 08:01 245836     /lib/libc-2.12.1.so
    00317000-00318000 ---p 00157000 08:01 245836     /lib/libc-2.12.1.so
    00318000-0031a000 r--p 00157000 08:01 245836     /lib/libc-2.12.1.so
    0031a000-0031b000 rw-p 00159000 08:01 245836     /lib/libc-2.12.1.so
    0031b000-0031e000 rw-p 00000000 00:00 0 
    00376000-00377000 r-xp 00000000 00:00 0          [vdso]
    00852000-0086e000 r-xp 00000000 08:01 245783     /lib/ld-2.12.1.so
    0086e000-0086f000 r--p 0001b000 08:01 245783     /lib/ld-2.12.1.so
    0086f000-00870000 rw-p 0001c000 08:01 245783     /lib/ld-2.12.1.so
    08048000-08051000 r-xp 00000000 08:01 2244617    /bin/cat
    08051000-08052000 r--p 00008000 08:01 2244617    /bin/cat
    08052000-08053000 rw-p 00009000 08:01 2244617    /bin/cat
    09ab5000-09ad6000 rw-p 00000000 00:00 0          [heap]
    b7502000-b7702000 r--p 00000000 08:01 4456455    /usr/lib/locale/locale-archive
    b7702000-b7703000 rw-p 00000000 00:00 0 
    b771b000-b771c000 r--p 002a1000 08:01 4456455    /usr/lib/locale/locale-archive
    b771c000-b771e000 rw-p 00000000 00:00 0 
    bfbd9000-bfbfa000 rw-p 00000000 00:00 0          [stack]
    

    【讨论】:

    • 一些发行版(例如 RHEL6)甚至完全放弃了 0x08048000 东西,将程序与 DYNAMIC flag 链接在一起,使它们的段与 .so 一起分配。
    【解决方案2】:

    加载可执行代码的起始地址由可执行文件的 ELF 标头确定。例如:

    /bin/ls
    architecture: i386, flags 0x00000112:
    EXEC_P, HAS_SYMS, D_PAGED
    start address 0x08049bb0
    

    没有什么可以阻止可执行文件指定不同的加载地址;不管出于什么原因default linker settings 把它放在那里。您可以使用自定义链接描述文件覆盖。

    默认情况下,在 linux/x86 上,您不会看到0x08000000 以下的低地址被大量使用;尽管内核可能会在mmap 调用中请求它,或者如果它的mmap 空间不足。此外,有人提议使用0x00000000 - 0x01000000 范围内的地址进行库映射,以使缓冲区溢出更加困难(通过嵌入 NUL 字节来终止字符串)。

    【讨论】:

    • 所有进程都有独立的虚拟地址转换表。所以很多可能有相同的起始地址,转换成不同的物理地址。
    【解决方案3】:

    加载地址是任意的,但使用 SYSV for x86 标准化。每种架构都不同。上面和下面的内容也是任意的,并且经常被库和 mmap() 区域中的链接所占用。

    【讨论】:

      【解决方案4】:

      32 位小型静态应用的 x86 的典型负载图如下所示:

       Address     Contents
      
       0x08048000  code
       0x08052000  data
       0x0805A000  bss (zero data)
       0x08072000  end of data (brk marker)
       0xBFFFE000  stack
      

      所有这些都是相反的 - 堆栈在顶部并在数据向上移动时向下移动。我的猜测是 0x08048000 之前的地址是静态链接的,类似于每个操作系统的 MBR。

      【讨论】:

      • 如果您的程序映像在 0x0848000 加载,您将看不到任何低于该位置的内容 - 没有“MBR”或任何内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-25
      • 2010-09-27
      • 2017-10-04
      • 2017-07-16
      • 2019-05-20
      相关资源
      最近更新 更多