Linux下进程的内存布局

目录

目录

进程空间内存布局  

非初始化数据段

初始化数据段

文本段也称代码段

Linux下内存布局分布图

Linux C/C++语言的分配方式的 3 种方式


扫描二维码关注公众号,回复: 11007280 查看本文章

进程空间内存布局  

 在深入理解Linux下多进程编程之前,我们首先要了解Linux下进程在运行时的内存布局。Linux 进程内存管理的对象都是虚拟 内存,每个进程先天就有 0-4G 的各自互不干涉的虚拟内存空间,0—3G 是用户空间执行用户自己的代码, 高 1GB 的空间是内核 空间执行 Linu x 系统调用,这里存放在整个内核的代码和所有的内核模块,用户所看到和接触的都是该虚拟地址,并不是实际 的物理内存地址。 Linux下一个进程在内存里有三部分的数据,就是”代码段”、”堆栈段”和”数据段”。其实学过汇编语言 的人一定知道,一般的CPU都有上述三种段寄存器,以方便操作系统的运行。这三个部分是构成一个完整的执行序列的必要的部 分。”代码段”,顾名思义,就是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用相同的代码段。”堆栈段”存放的就是子程 序的返回地址、子程序的参数以及程序的局部变量和malloc()动态申请内存的地址。而 数据段则存放程序的全局变量,静态变量及常量的内存空间。    

 栈内存由编译器在程序编译阶段完成,进程的栈空间位于进程用户空间的顶部并且是向下增长,每个函数的每次调用 都会在栈空间中开辟自己的栈空间,函数参数、局部变量、函数返回地址等都会按照先入者为栈顶的顺序压入函数栈中, 函数返回后该函数的栈空间消失,所以函数中返回局部变量的地址都是非法的。

堆内存是在程序执行过程中分配的,用于存放进程运行中被动态分配的的变量,大小并不固定,堆位于非初始化数据 段和栈之间,并且使用过程中是向栈空间靠近的。当进程调用 malloc 等函数分配内存时,新分配的内存并不是该函数的 栈帧中,而是被动态添加到堆上,此时堆就向高地址扩张;当利用 free 等函数释放内存时,被释放的内存从堆中被踢 出,堆就会缩减。因为动态分配的内存并不在函数栈帧中,所以即使函数返回这段内存也是不会消失。

  • 非初始化数据段

通常将此段称为 bss 段,用来存放未初始化的全局变量和 static 静态变量。并且在程序开始执行之前, 就是在 main()之前,内核会将此段中的数据初始化为 0 或空指针。 

  • 初始化数据段

用来保已初始化的全局变量和 static 静态变量。 

  • 文本段也称代码段

这是可执行文件中由 CPU 执行的机器指令部分。正文段常常是只读的,以防止程序由于意外而修改 其自身的执行。 Linux 内存管理的基本思想就是只有在真正访问一个地址的时候才建立这个地址的物理映射。

  • Linux下内存布局分布图

  • Linux C/C++语言的分配方式的 3 种方式

  • 从静态存储区域分配。

    就是数据段的内存分配,这段内存在程序编译阶段就已经分配好,在程序的整个运行期间都存在, 例如全局变量,static 变量。      

  • 在栈上创建。

    在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。 栈内存分配运算内置于处理器的指令集中,效率很高,但是系统栈中分配的内存容量有限,比如大额数组就会把栈空间撑爆导致 段错误。  

  • 从堆上分配,亦称动态内存分配。

   程序在运行的时候用 malloc 或 new 申请任意多少的内存,程序员自己负责在何时用 free 或 delete 释放内存。此 区域内存分配称之为动态内存分配。动态内存的生存期由我们决定,使用非常灵活,但问题也 多,比如指向某个内存块的指针取值发生了变化又没有其他指针指向 这块内存,这块内存就无法访问,发生内存泄露。

发布了47 篇原创文章 · 获赞 37 · 访问量 3707

猜你喜欢

转载自blog.csdn.net/qq_44045338/article/details/104730375