对程序内存结构和程序存储位置的理解
2018-02-02 00:00
369 查看
对程序内存结构和程序存储位置的理解
之前看过许多有关系统中,对内存分配的一些文章,一直一知半解,直到调研一个系统调用,才真正的弄明白是怎么回事. 有一个重点就是,这里说的全局数据区,全局,说的不说c++中的全局的概念,如果那样理解很容易感觉模棱两可,这里说的全局说 系统看来,不是一个程序的看待,对系统来说,一个程序的全局就是,需要在程序运行前准备好的内存,对于c++中的变量,系统看来只有三种:全局,stack,bss, 其他两个,stack管程序调用,bss指需要,但是运行的时候才能知道内容. 加载慢的一个优化手段就是,调整程序,让bss代替data,具体为什么,下文会说,这个内容想写写来源于对一个系统调用的研究 brk(void* addr), 某些程序加载的时候cpu很高,使用strace -p PID查看以后,发现他 一直执行brk这个系统调用.
brk: 调整程序的数据段,把数据段的地址往高地址调整,,,,,这个有啥用?地址段不是应该加载的时候分配好的吗?有的说这个还能分配动态内存,动态内存不是在heep区分配的吗?总之疑点重重.
一般系统中的地址分配都是从低到高, 依次是:
text段 => 存放指令代码,在可执行文件中也由这一部分,系统会把文件中的text端拷贝到内存里
bss段 => 未初始化的全局数据区,一般系统会弄成0,这一部分在可执行文件中是没有的,只是记录一下需要多少这种空间
data数据段 => 这一部分比较特殊,下文会具体说明,可执行文件中可能有也可能没有.
——-> 这有个指针(系统用的,不过用户态可以通过调用修改) _edata
heep堆 => 这是通常 认为 的malloc申请内存的地方,其实也不一定的,下文会说
stack栈地址 => 栈地址,通常的函数调式都会用到的,
==>
==>
3G以上就是内核区了,用户态就别想自由使用了.
brk的功能就是,把 _edata的地址网高出推,往 heap这边推,可以想象,brk把_data往heep推了,heep能分配的空间肯定就少了啊,
对的,是这样的,
有关brk分配内存的说明
c语言中分配内存,当然是使用malloc了,brk分配内存的功能,就是在这里的,glibc对malloc的实现,是如果分配的内存在 126k以内, 就使用brk分配,把brk往heep端推一点,多余出来的数据段,返回给用户,用作动态内存,当读写这个内存的时候,就会引发一个 缺页中断 让系统在物理内存里分配段内存. 126k以内都用brk,我们平时试试的基本都是使用brk分配的啊,我不信!!,我写个程序给你证明
#include<iostream> #include<unistd.h> #include<stdlib.h> using namespace std; int main(){ void*p = malloc(1); cout<<p<<endl; int a = brk((void*)((char*)p+1000)); //这句调步调影响下次malloc返回的地址 //int a = brk((void*)((char*)p+1)); cout<<a<<endl; void* d=malloc(1); cout<<d<<endl; return 0; }
一开始我使用 brk(p+1) 程序直接崩溃了,后来查了一下两次malloc的地址差,发现一次malloc 已经把_edata的地址上调了460了,如果我在上调,只能调这个数更大的范围了, 这里有个隐含规则 brk 的地址,只能往高处调,不能往低处调,因为已经调好的内存, 可能已经分配了,我们私自把地址往下调了,brk也返回成功0,可是程序会直接崩溃.
如果malloc申请的地址超过了126k,才会调用mmap到heap区去申请内存. brk和heap是linux系统调用,malloc是glibc的函数,不是系统调用.
如果_edata只能往上调,那麽,即使malloc把内存释放了,把_edata调下来,也只能依次释放的,可是用户程序不一定这样来,这不就是 浪费吗? 是的,是这样,用户free,这个地址的一段内存就不能回收了,只有当最高处的地址被free了, 才能把_edata调下来,同时通知系统,取消映射. malloc默认没有一个一个字节的向高地址加,而是一次就加许多,这个许多如何知道呢,这个和系统分配的页大小有关,查看办法如下: 使用getconf PAGESIZE 查看系统的页大小
相关文章推荐
- C程序存储空间布局—各数据段的内存位置
- C程序存储空间布局(一)——各数据段的内存位置
- C程序存储空间布局——各数据段的内存位置
- C程序的存储内存空间
- C++类的存储及类对象内存结构(整理)
- Wince6.0 存储内存与程序内存比例调整
- Mac下MySQL的位置和内容结构,存储数据的目录
- java+内存分配及变量存储位置的区别
- 【Hadoop】一图学习HDFS源码结构系列——内存存储Lazy persist
- 变量和值在内存中的存储位置
- 理解 Android 本地数据存储 API--利用首选项、SQLite 和内部及外部内存 API
- memcached全面剖析–2.理解memcached的内存存储
- 第2章 理解memcached的内存存储
- java 基础教程之一程序在内存中的位置
- C/C++学习(8)变量在内存中的存储位置
- JVM学习(2)-Java常量,变量,对象(字面量)在内存中的存储位置
- 深入理解vector list deque——存储结构机理
- 实验 3.1.5 查看代码中各数据存储位置 示例程序: mem_add.c 1. 在自己的机器上运行示例程序。 2. 分析实验结果,图示程序运行时各数据位置。
- 结构体存储内存对齐
- linux进程存储管理--进程内存结构