【问题标题】:Question about Linux process memory layout关于Linux进程内存布局的问题
【发布时间】:2011-09-29 10:26:42
【问题描述】:

我说的是英特尔 32 位平台。 Linux 内核版本 2.6.31-14。

#include <stdio.h>
#include <stdlib.h>

int init_global_var = 10;        /* Initialized global variable */
int global_var;                  /* Uninitialized global variable */
static int init_static_var = 20; /* Initialized static variable in global scope */
static int static_var;           /* Uninitialized static variable in global scope */

int main(int argc, char **argv, char **envp)
{
        static int init_static_local_var = 30;   /* Initialized static local variable */
    static int static_local_var;             /* Uninitialized static local variable */
    int init_local_var = 40;                 /* Initialized local variable */
    int local_var;                           /* Uninitialized local variable */
    char *dynamic_var = (char*)malloc(100);  /* Dynamic variable */

    printf("Address of initialized global variable: %p\n", &init_global_var);
    printf("Address of uninitialized global variable: %p\n", &global_var);
    printf("Address of initialized static variable in global scope: %p\n", &init_static_var);
    printf("Address of uninitialized static variable in global scope: %p\n", &static_var);
    printf("Address of initialized static variable in local scope: %p\n", &init_static_local_var);
    printf("Address of uninitialized static variable in local scope: %p\n", &static_local_var);
    printf("Address of initialized local variable: %p\n", &init_local_var);
    printf("Address of uninitialized local variable: %p\n", &local_var);
    printf("Address of function (code): %p\n", &main);
    printf("Address of dynamic variable: %p\n", dynamic_var);
    printf("Address of environment variable: %p\n", &envp[0]);
    char* p=0x0;
    printf("%s\n",p);

    exit(0);
}

输出:

naman@naman-laptop ~> ./a.out
Address of initialized global variable: 0x804a020
Address of uninitialized global variable: 0x804a03c
Address of initialized static variable in global scope: 0x804a024
Address of uninitialized static variable in global scope: 0x804a034
Address of initialized static variable in local scope: 0x804a028
Address of uninitialized static variable in local scope: 0x804a038
Address of initialized local variable: 0xbfc11cbc
Address of uninitialized local variable: 0xbfc11cb8
Address of function (code): 0x8048484
Address of dynamic variable: 0x8223008
Address of environment variable: 0xbfc11d7c
fish: Job 1, “./a.out” terminated by signal SIGSEGV (Address boundary error)

在上面的代码中,我有以下困惑。 为什么代码位于0x8048484,而不是靠近虚拟内存开头的某个位置,比如0x00000400?据我所知,布局应该是这样的:

内存不足.......................................HighMemory

Text Data BSS Heap.....................Stack Env

所以,文本不应该在内存中太远。它应该靠近较低的内存,不是吗?

【问题讨论】:

    标签: linux process memory-layout


    【解决方案1】:

    为什么代码位于 0x8048484

    因为默认加载地址(ELF 文件的开头将在此地址加载)是 0x8000000(或 0x8048000)。此默认值在默认链接器 (ld) 脚本中是固定的,并且可以通过链接器选项进行更改。

    注意,这是 0x08000000 或 0x08048000(128 兆字节),而不是 0x80000000(2 千兆字节)。

    这里有一些关于此限制的讨论 http://cboard.cprogramming.com/tech-board/101129-why-address-space-0-0x08000000-process-unused.html 在论坛和 http://books.google.com/books?id=Id9cYsIdjIwC&pg=PA111&lpg=PA111&dq=linker+0x08000000 在书籍中。 还有 http://lkml.org/lkml/2002/2/20/194 在 lkml 有很好的描述:

    "0x8048000 是文本段的典型起点,根据 符合 System V Intel 386 ABI 规范 (http://stage.caldera.com/developer/devspecs/abi386-4.pdf)。”

    【讨论】:

    • 这仅适用于 ELF 或任何可执行格式?就像这里我的文件是 .out (我认为它与 ELF 不同,我可能错了)。另外,这取决于可执行文件格式还是linux进程加载器的属性?
    • 要获取文件格式,使用命令file FILENAME,例如file a.out。您将看到您有一个 ELF 文件。 “a.out”名称是默认可执行文件名称的历史名称。现在不使用 a.out 文件格式。链接描述文件特定于文件格式,但 COFF/A.OUT 脚本可能具有相似的加载地址。这是 ABI、静态链接器 (ld) 和(部分)动态链接器 (ld-linux.so) 的属性
    【解决方案2】:

    a.out 什么时候不是 a.out?当它实际上是一个ELF时。详情请尝试elfinfo --all a.out

    【讨论】:

    • 但是为什么它是从 0x08000000 开始而不是从 0x00100000 开始呢?
    猜你喜欢
    • 2017-06-20
    • 2016-12-15
    • 2013-05-24
    • 1970-01-01
    • 2013-03-07
    • 2016-03-26
    • 2013-07-12
    • 2019-08-21
    相关资源
    最近更新 更多