===系统内存===
系统内存的使用情况可以用以下公式表示:
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