Linux进程1——地址空间

1.进程虚拟内存分配

  在Linux系统中,每个进程都具体自己独立的4GB虚拟内存空间,包括3GB的用户空间和1GB内核空间。每个程序被编译后,成为可执行程序,

变量和函数的地址都被分配完成。可执行程序内部被划分为多个区域,包括.text,.data,.bss等区域。

  (1).text为代码段,可执行程序在内存中副本,const全局变量、字符串常量等,只读操作。

  (2).data为数据段,程序中已经被初始化的全局变量,读写操作。

  (3).bss为程序中未初始化的全局变量,加载时有OS初始化为0。

  

 

2.程序代码分析

//main.c

#include <stdio.h>

int global_init_a = 1;
int global_init_b = 1;

int global_uninit_a;
int global_uninit_b;

const int const_global_init_a = 1;
const int const_global_init_b = 1;

static int static_global_init_a = 1;
static int static_global_init_b = 1;

static int static_global_uninit_a;
static int static_global_uninit_b;

void DisplayVar(char* name,int* addr)
{
    printf("%-24s\taddr = 0x%x\n",name,(unsigned int)addr);
}

int main(int argc,char* argv[])
{
    int local_init_a = 1;
    int local_init_b = 1;

    int local_uninit_a;
    int local_uninit_b;

    const int const_local_init_a = 1;
    const int const_local_init_b = 1;

    static int static_local_init_a = 1;
    static int static_local_init_b = 1;

    static int static_local_uninit_a;
    static int static_local_uninit_b;

    DisplayVar("global_init_a",&global_init_a);
    DisplayVar("global_init_b",&global_init_b);
    DisplayVar("global_uninit_a",&global_uninit_a);
    DisplayVar("global_uninit_b",&global_uninit_b);
    DisplayVar("const_global_init_a",&const_global_init_a);
    DisplayVar("const_global_init_b",&const_global_init_b);
    DisplayVar("static_global_init_a",&static_global_init_a);
    DisplayVar("static_global_init_b",&static_global_init_b);
    DisplayVar("static_global_uninit_a",&static_global_uninit_a);
    DisplayVar("static_global_uninit_b",&static_global_uninit_b);

    DisplayVar("local_init_a",&local_init_a);
    DisplayVar("local_init_b",&local_init_b);
    DisplayVar("local_uninit_a",&local_uninit_a);
    DisplayVar("local_uninit_b",&local_uninit_b);
    DisplayVar("const_local_init_a",&const_local_init_a);
    DisplayVar("const_local_init_b",&const_local_init_b);
    DisplayVar("static_local_init_a",&static_local_init_a);
    DisplayVar("static_local_init_b",&static_local_init_b);
    DisplayVar("static_local_uninit_a",&static_local_uninit_a);
    DisplayVar("static_local_uninit_b",&static_local_uninit_b);
  
  while(1);
return 0; }

运行结果:

$ ./main
global_init_a                   addr = 0x8049a48
global_init_b                   addr = 0x8049a4c
global_uninit_a                 addr = 0x8049a78
global_uninit_b                 addr = 0x8049a74
const_global_init_a             addr = 0x8048690
const_global_init_b             addr = 0x8048694
static_global_init_a            addr = 0x8049a50
static_global_init_b            addr = 0x8049a54
static_global_uninit_a          addr = 0x8049a64
static_global_uninit_b          addr = 0x8049a68
local_init_a                    addr = 0xbf91b9dc
local_init_b                    addr = 0xbf91b9d8
local_uninit_a                  addr = 0xbf91b9d4
local_uninit_b                  addr = 0xbf91b9d0
const_local_init_a              addr = 0xbf91b9cc
const_local_init_b              addr = 0xbf91b9c8
static_local_init_a             addr = 0x8049a58
static_local_init_b             addr = 0x8049a5c
static_local_uninit_a           addr = 0x8049a6c
static_local_uninit_b           addr = 0x8049a70

3.分析结果

  ps -aux | grep a.out    //获取pid

 

  cat /proc/19762/maps    //通过pid获取map信息

 

$ cat /proc/19762/maps
08048000-08049000 r-xp 00000000 08:01 1588082    /home/bill/blog/main
08049000-0804a000 rw-p 00000000 08:01 1588082    /home/bill/blog/main
b75a6000-b75a7000 rw-p 00000000 00:00 0
b75a7000-b774e000 r-xp 00000000 08:01 786482     /lib/i386-linux-gnu/i686/cmov/libc-2.19.so
b774e000-b7750000 r--p 001a7000 08:01 786482     /lib/i386-linux-gnu/i686/cmov/libc-2.19.so
b7750000-b7751000 rw-p 001a9000 08:01 786482     /lib/i386-linux-gnu/i686/cmov/libc-2.19.so
b7751000-b7754000 rw-p 00000000 00:00 0
b775b000-b775e000 rw-p 00000000 00:00 0
b775e000-b775f000 r-xp 00000000 00:00 0          [vdso]
b775f000-b7761000 r--p 00000000 00:00 0          [vvar]
b7761000-b7780000 r-xp 00000000 08:01 786518     /lib/i386-linux-gnu/ld-2.19.so
b7780000-b7781000 r--p 0001f000 08:01 786518     /lib/i386-linux-gnu/ld-2.19.so
b7781000-b7782000 rw-p 00020000 08:01 786518     /lib/i386-linux-gnu/ld-2.19.so
bff07000-bff28000 rw-p 00000000 00:00 0          [stack]

 

4.分析ELF程序结构

  Linux可执行程序符合ELF结构,通过readelf指令可以查看程序结构。

 

$ readelf -S main
There are 30 section headers, starting at offset 0x1424:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        08048134 000134 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4
  [ 3] .note.gnu.build-i NOTE            08048168 000168 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        0804818c 00018c 000020 04   A  5   0  4
  [ 5] .dynsym           DYNSYM          080481ac 0001ac 000050 10   A  6   1  4
  [ 6] .dynstr           STRTAB          080481fc 0001fc 00004c 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          08048248 000248 00000a 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         08048254 000254 000020 00   A  6   1  4
  [ 9] .rel.dyn          REL             08048274 000274 000008 08   A  5   0  4
  [10] .rel.plt          REL             0804827c 00027c 000018 08  AI  5  12  4
  [11] .init             PROGBITS        08048294 000294 000023 00  AX  0   0  4
  [12] .plt              PROGBITS        080482c0 0002c0 000040 04  AX  0   0 16
  [13] .text             PROGBITS        08048300 000300 000362 00  AX  0   0 16
  [14] .fini             PROGBITS        08048664 000664 000014 00  AX  0   0  4
  [15] .rodata           PROGBITS        08048678 000678 000191 00   A  0   0  4
  [16] .eh_frame_hdr     PROGBITS        0804880c 00080c 000034 00   A  0   0  4
  [17] .eh_frame         PROGBITS        08048840 000840 0000d4 00   A  0   0  4
  [18] .init_array       INIT_ARRAY      08049914 000914 000004 00  WA  0   0  4
  [19] .fini_array       FINI_ARRAY      08049918 000918 000004 00  WA  0   0  4
  [20] .jcr              PROGBITS        0804991c 00091c 000004 00  WA  0   0  4
  [21] .dynamic          DYNAMIC         08049920 000920 0000e8 08  WA  6   0  4
  [22] .got              PROGBITS        08049a08 000a08 000004 04  WA  0   0  4
  [23] .got.plt          PROGBITS        08049a0c 000a0c 000018 04  WA  0   0  4
  [24] .data             PROGBITS        08049a24 000a24 000020 00  WA  0   0  4
  [25] .bss              NOBITS          08049a44 000a44 00001c 00  WA  0   0  4
  [26] .comment          PROGBITS        00000000 000a44 000039 01  MS  0   0  1
  [27] .shstrtab         STRTAB          00000000 000a7d 000106 00      0   0  1
  [28] .symtab           SYMTAB          00000000 000b84 000520 10     29  53  4
  [29] .strtab           STRTAB          00000000 0010a4 000380 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

 

posted on 2017-08-06 16:22  生活的艺术  阅读(283)  评论(0)    收藏  举报