🧱 一、总览结构类问题(Memory Layout)
- Linux 进程的虚拟地址空间是如何划分的?主要有哪些区域?
- 进程虚拟地址空间的增长方向是怎样的?各区域是向高地址还是低地址增长?
- 32位与64位下虚拟地址空间的差异有哪些?地址上限是多少?
- 用户态和内核态地址空间分别占多少?在哪个范围?
- 进程的每个虚拟地址是否都有对应的物理内存?
📄 二、Text(代码段)
- 代码段在进程虚拟地址空间的哪一部分?它的访问权限是什么?
- 常量字符串是否存储在 text 段中?为什么?
- 是否可以修改 text 段中的内容?如果尝试写会发生什么?
- 多个进程是否可以共享 text 段?
📦 三、Data(已初始化数据段)
- 什么样的变量存储在数据段中?请举例说明。
- 数据段的内存权限默认是什么?可以执行吗?
- 全局变量和静态变量都在数据段吗?
🐣 四、BSS(未初始化数据段)
BSS 和数据段有什么区别?
以下代码中变量a和变量b分别在哪个段中?
int a = 0; // ? int b; // ?
BSS段在物理内存中是否占空间?程序启动前是如何初始化的?
BSS段的大小能否通过查看编译后的 ELF 文件得知?
🌱 五、Heap(堆)
- 堆区的分配从哪个系统调用接口开始?默认增长方向是什么?
- 使用 malloc/free 时实际是操作堆区吗?背后调用了什么?
- 堆区的起始和结束地址如何查看?
- heap 使用的内存分配机制是基于哪两个系统调用?
- 堆内存什么时候会被内核收回?
🌀 六、Stack(栈)
- 栈的增长方向是怎样的?
- 局部变量和函数参数存储在栈中还是堆中?
- 栈溢出会导致什么错误?Linux 默认栈大小是多少?如何修改?
- 递归函数调用栈太深会发生什么?如何调试?
- 每个线程是否有独立的栈空间?怎么控制其大小?
📚 七、Memory-mapped Region(mmap 区)
- 什么是 mmap 区?由谁管理?通常用于什么目的?
- 动态库的加载是否属于 mmap 区域?
- 使用 malloc 时什么时候会转向使用 mmap?
- 匿名 mmap 与文件映射 mmap 有何区别?
- 使用
mmap
分配内存和malloc
的最大区别是什么?
🧪 八、虚拟内存和物理内存映射相关问题
- 如何通过页表实现虚拟地址到物理地址的映射?
- 一个虚拟地址可能对应多个物理地址吗?反之呢?
- TLB(Translation Lookaside Buffer)在虚拟地址转换中起什么作用?
- 如何查看某个进程的虚拟内存布局?用哪个命令?
- 某段虚拟内存被 swap 到磁盘时会发生什么?
🔐 九、内存权限控制(Protection)
- 各段的典型权限是什么(如 text、data、heap、stack)?
- 使用
mprotect()
可以做什么?举例说明其作用。 - 什么是 NX(Non-eXecutable) 位,它有什么安全作用?
- 可以让堆或栈变为可执行吗?如何操作?有何风险?
🔍 十、实用调试/查看命令类
- 如何使用
/proc/[pid]/maps
来查看进程的内存映射?能看到哪些信息? - 如何使用
pmap
命令查看进程各段占用的内存? - 如何使用
gdb
查看某个变量所在的内存段? - 如何判断内存是否映射了共享对象(.so 文件)?
- valgrind 检测内存访问错误和泄漏时,是如何理解各段内存的?
🚧 十一、其他高级内存区域相关
- 什么是匿名映射?在 mmap 区中怎么实现匿名共享内存?
- Thread Local Storage(TLS)在内存中属于哪个区域?
- VDSO 是什么?它位于哪个区域?作用是什么?
- 栈溢出与堆溢出在内存结构上有何区别?如何防护?
- 如何使用
ulimit
控制进程的堆/栈大小?