Linux进程虚拟内存空间布局/ Linux 下虚拟内存的分布
Posted 想文艺一点的程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux进程虚拟内存空间布局/ Linux 下虚拟内存的分布相关的知识,希望对你有一定的参考价值。
目录
注意:
进程虚拟内存空间布局 ===== 虚拟内存的分布
1、在 32 位的操作系统当中,理论的内存空间为 4G
2、在 Linux 当中,每个进程都以为自己独占整个用户态的内存空间。
3、一般来说 内核空间:用户空间 === 4:1 (比例也可以在内核里面进行修改)
摆上一个内存分布图:
用户空间内存分析
3G:0x0000 0000 —— 0xc000 0000
权限:
R :可读、read
W:可写、write
E:可执行 execve
内存划分 | 名称 | 权限 | 分析 |
---|---|---|---|
0x0000 0000 —— 0x0804 8000 | Reserved(保留区) | 没有真实的物理地址,用于空指针指向,避免产生野指针。 | |
0x0804 8001 —— 0xbFFF FFFF | Text Segment | R/E | 代码指令、字符串常量、其他常量 |
Data Segment | R/W | 已经初始化的全局变量,static 变量 | |
BSS Segment | R/W | 未初始化的全局变量,static 变量,然后全部清零 | |
自由偏移 | Random offset | 防止堆区的数据被攻击,加一层保护 | |
Heap | R/W | 用户自己管理的内存 | |
Memory Mapping Segment | 用来装载动态内存共享库 | ||
自由偏移 | Random offset | ||
Stack | R/W | 系统自己分配(一般最大为 64MB) | |
自由偏移 | Random offset |
1、Reserved(保留区)
- 这段区域是不允许进行访问的,否则会发生段错误。
- 位于虚拟地址空间的最低部分,未赋予物理地址。
- 任何对它的引用都是非法的,用于捕捉使用空指针和小整型值指针引用内存的异常情况。(int *p = NULL)
2、Text 代码段
- 一般存放程序执行的代码,即 cpu 执行的机器指令,还有字符串常量。
- 一个函数体在代码段只有一份代码,函数调用的本质:其实就是一句跳转指令 call xxxx
- 通常为只读,但是有些架构允许进行写操作。
3、Data 数据段
- 存放 已经初始化的全局变量和 static 变量
4、BSS 段
-
存放 未初始化的全局变量和 static 变量
留:
5、Heap 堆
- 其中的内容是匿名的,只能通过指针来进行访问。
6、mmap 内存映射段
- 将硬盘当中的文件内容直接映射到内存。
- Linux 当中任何应用程序,都可以通过 mmap() 的API 接口,来请求这种映射。
- 因为是硬盘内容的直接映射,所以这是一种非常高效的 文件I/O 方式。 一般用来装载动态共享库。
7、Stack 栈
8、Random offset
在这个区域上有一个Random stack offset(栈随机偏移),这个偏移的主要作用是安全起见。
因为内存布局按照严格的规则摆放,因此很容易被恶意访问,通过加入随机偏移,使的每个进程的栈空间起始位置都稍有不同,使的被确定栈空间起始位置具有一定难度,防止被恶意访问。后面的Random brk offset等也是同理。
分析进程/程序
1、变量是什么?
-
编译器会将对应的变量名,转化为内存地址。
-
变量在 CPU 来看,就是一个内存地址。
赋值指令:本身属于代码,会放到代码段。
作用:就是给一个特定的内存进行赋值。
2、函数的调用:
程序执行的本质:在代码段跳来跳去。 (因为所有的指令都在代码段)
- 可以看出,0x0076 1D3C 和 0x0076 14E7 相差并不远,肯定都在代码段。
- 在调用子函数的时候,会将什么东西压栈呢?
(下一条指令的地址,实参的值)
以上是关于Linux进程虚拟内存空间布局/ Linux 下虚拟内存的分布的主要内容,如果未能解决你的问题,请参考以下文章