Linux-虚拟地址空间分布-笔记
Linux系统下,内核进程和用户进程所占的虚拟内存比例为1:3;
windows系统下,内核进程和用户进程所占的虚拟内存比例为2:2(也可以修改为1:3);
虚拟地址通过页表映射到物理地址,页表由操作系统维护并被处理器引用。(Linux系统通过对栈、堆、内存映射段的起始地址加上随机偏移量来打乱布局,避免恶意程序通过计算访问栈、库函数等地址);
用户进程部分分段存储内容按照地址递减:
内核空间: 内核总是驻留在内存中,其是操作系统的一部分。内核空间所占区域为内核所保留,不允许应用程序读写该区域或直接调用内核代码定义的函数。
栈: 又称为堆栈,由编译器自行分配释放。有三个用途1.为函数内部声明的非静态局部变量提供存储空间。2.栈帧或过程活动记录,记录函数调用过程相关的维护性信息,包括函数返回地址等等。3.临时存储区,用于存储长算术表达式部分计算结果。在linux中ulimit -s命令可以查看和设置堆栈的最大值,当程序使用超过该值时,发生栈溢出,程序会收到段错误,此时可向上或者向下调整栈的容量,这依赖于具体的实现。
堆: 堆用来存放进程运行时动态分配的内存段,可以动态扩张或者缩减(末端break指针标识,通过系统调用brk()和sbrk()来移动break指针以扩张堆),但是其内容是匿名的,只能通过指针间接访问。由于堆的内存申请和释放是无序的,所以会在最后产生内存碎屑,如果程序员不释放最后程序结束时操作系统会自行释放收回内存。通常有两类问题:内存泄露和内存破坏。
BSS段: 通常存放以下符号:未初始化的全局变量和静态局部变量;初始值为0的全局变量和静态局部变量;未定义且初值不为0的符号;
数据段: 通常存放程序中已经初始化且初值不为0的全局变量和静态局部变量,数据段属于静态内存分配(可读可写);
运行时,数据段和BSS段通常合称数据区。
代码段: 正文段、文本段、通常存放程序执行代码(机器指令),频繁执行的代码段是共享的,只需要在用的时候拷贝一份,通常只读。
保留区: 虚拟地址空间的最底部,未给予物理地址,用于捕捉使用空指针和小整形指针引用内存的异常情况。