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)
浙公网安备 33010602011771号