系统内存和进程内存

===系统内存===

系统内存的使用情况可以用以下公式表示:
MemTotal = MemFree +【Slab+ VmallocUsed + PageTables + KernelStack + HardwareCorrupted + Bounce + X】+【Active + Inactive + Unevictable + (HugePages_Total * Hugepagesize)】
MemTotal = MemFree +【Slab+ VmallocUsed + PageTables + KernelStack + HardwareCorrupted + Bounce + X】+【Cached + AnonPages + Buffers + (HugePages_Total * Hugepagesize)】
MemTotal = MemFree +【Slab+ VmallocUsed + PageTables + KernelStack + HardwareCorrupted + Bounce + X】+【ΣPss + (Cached – mapped) + Buffers + (HugePages_Total * Hugepagesize)】

File-backed内存,anon匿名内存,Shmem是tmpfs所使用的内存

=cached是和file有关的所有文件映射和文件系统
【buffers + cached 】= 【Active(file) + Inactive(file) + Shmem 】

=AnonPages不算tmpfs,shmem,纯进程申请malloc和占用内存
【Active(anon)+Inactive(anon)+(mlock=Unevictable)】 = 【AnonPages + Shmem】

=ΣPss = grep Pss /proc/[1-9]*/smaps | awk '{total+=$2}; END {print total}'
【AnonPages】=【ΣPss – mapped】
mapped包括代码段和数据段

SHR是RES中”映射至文件”的物理内存总和。包括:
程序的代码段。
动态库的代码段。
通过mmap做的文件映射。
通过mmap做的匿名映射,但指明了MAP_SHARED属性。
通过shmget申请的共享内存。
/proc//smaps内Shared_*统计的是RES中映射数量>=2的物理内存。
/proc//smaps内Private_*统计的是RES中映射数量=1的物理内存。

===进程内存===

程序编译:预编译hello.i,编译hello.s,汇编hello.o,连接a.out
ELF文件一共有4种类型:Relocatable file、Executable file、Shared object file和Core Dump file
.o文件,目标文件只是ELF文件的可重定位文件(Relocatable file)
.so文件是Shared object file
bin可执行文件是Executable file

文件结构:text代码段,data数据段,bss预留段,other sections,(只读,注释,堆栈)
sectios table,string table,symbol table

1,ELF文件大小
    size:    输出指定输入文件各段及其总和的大小
    text       data        bss        dec        hex    filename
    1492        564         12       2068        814    sleep

ELF文件提供两种视图,使用objdump工具和readelf工具可以查看分析elf文件的格式
link:ELF header,program header table,sections,section header table
exec:ELF header,program header table,segments,section header table

- ELF header: 描述整个文件的组织。
- Program Header Table: 描述文件中的各种segments,用来告诉系统如何创建进程映像的。
- sections 或者 segments:segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,
    也就是说,在链接阶段,我们可以忽略program header table来处理此文件,
    在运行阶段可以忽略section header table来处理此程序
    segments与sections是包含的关系,一个segment包含若干个section。
    当ELF文件被加载到内存中后,系统会将多个具有相同权限(flg值)section合并一个segment
    如果section的长度不是其整数倍,则导致多余部分也将占用一个页
- Section Header Table: 包含了文件各个segction的属性信息

对比三类ELF文件,我们得到了以下结论: 
(1)e_type标识了文件类型 
(2)Relocatable File(.o文件)不需要执行,因此e_entry字段为0,且没有Program Header Table等执行视图 
(3)不同类型的ELF文件的Section也有较大区别,比如只有Relocatable File有.strtab节


2,汇编程序
反汇编代码
查看源代码被翻译成的汇编代码, 大概有3种方法, 
1) 通过编译器直接从源文件生成, 如gcc -S 
2) 对目标代码反汇编, 一种是静态反汇编, 就是使用objdump
3) 另外一种就是对运行时的代码反汇编, 一般通过gdb disassemble
readelf并不提供反汇编功能. 
objdump -d,查看汇编

gdb主要功能的实现依赖于一个系统函数ptrace
gdb使用ptrace的基本流程
1、gdb调试一个新进程:通过fork函数创建一个新进程,
在子进程中执行ptrace(PTRACE_TRACEME, 0, 0, 0)函数,然后通过execv()调用准备调试的程序。
2、attach到已运行进程:将pid传递给gdb,然后执行ptrace(PTRACE_ATTACH, pid, 0, 0)

gdb 设置断点,向该地址写入断点指令INT3,即0xCC,发送SIGSTOP信号
gdb 单步调试,next指令时,会计算下一条语句对应的第一条指令的地址,然后控制目标程序走到该位置停止


3,看data和bss段内容
.data、.bss、.rodata都属于数据段。其中,
.data    存放已初始化的全局变量、常量、静态局部变量。
.bss    存放未初始化的全局变量,静态局部变量,所以此段数据均为0,仅作占位。
.rodata    是只读数据段,此段的数据不可修改,存放常量
static int x1 = 0;    bss段
static int x2 = 12;    data段

4,符号表是什么
查看ldd依赖项:objdump -x xxx.so | grep "NEEDED" 
查看动态符号表: objdump -T xxx.so
查看符号表: objdump -t xxx.so

上一篇:Mybatis 分页:Pagehelper + 拦截器实现


下一篇:为什么在x86 Linux中为elf可执行文件加载对齐地址的函数?