转自:http://www.hongkevip.com/caozuoxitong/Unix_Linux/24581.html

红客VIPhttp://www.hongkevip.com):Linux程序存储结构与进程结构堆和栈的区别

摘要:本文主要讲述了Linux系统中,程序存储结构(代码区、数据段和BBS区)与进程的基本结构(代码区、数据段、BBS区、堆和栈),以及堆和栈的区别.

Linux程序存储结构与进程结构 1.Linux程序存储结构 在Linux系统下,程序是一个普通的可执行文件,图1是一个Linux下ELF格式可执行文件的基本情况.

图1 ELF格式可执行文件的基本信息
可以看出,此ELF格式可执行文件在存储时,没有调入到内存,分为代码区(text),数据区(data)和为初始化区(bss)3个部分.各段基本说明如下:
(1)代码区(text segment).也称正文段.存放CPU可执行的机器指令,通常代码区是可共享的(即另外的执行代码可以访问调用它)代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指令.因此,常量数据在编译时在代码段中分配空间.例子1会说明这点.
代码区的指令包括操作码和操作对象(或对象的地址引用),如果是具体数值,将直接包含在代码中.如果是局部数据,将在运行时在栈区分配空间,然后再引用数据的地址;如果是BBS区和数据区,在代码中同样将引用该数据的地址.
(2)全局初始化数据区/静态数据区,或简称数据段.该区包含了在程序中明确被初始化的全局变量、已经初始化的静态变量(包括全局静态变量和局部静态变量).但被const声明的变量以及字符串常量在代码段中申请空间.
(3)未初始化数据区,也称BBS区.存入的是未初始化全局变量和未初始化静态变量.BBS区的数据在程序开始执行之前被内核初始化为0或者空指针(NULL).
例子1,,说明常量数据在编译时在代码段中分配空间.#include <stdio.h> int main() { char *buf =NULL; printf("%s\n",buf); return 0; }

编译后检测各段的大小:

在代码中添加一个字符常量和const数据常量:
#include <stdio.h> const int i=10; int main() { char *buf = NULL; printf("%s\n",buf); return 0; }

重新编译后查看:代码段的数据增加了4字节的const i.

2.Linux进程结构 在Linux系统下,如果将一个ELF格式可执行文件加载到内存中运行,则将演变成一个或多个进程.进程是Linux事务的基本管理单元,所有的进程均拥有自己的独立的环境和资源.进程的环境由当前系统状态及其父进程信息决定和组成.
一个正在运行的进程在内存空间中申请的代码区、初始化数据区、未初始化数据区、上下文信息以及挂载的信号等等.
(1)代码区.加载的是可执行文件的代码段,其加载到内存中的位置由加载器完成.
(2)全局初始化数据区/静态数据区.加载的是可执行文件数据段,位置可位于代码段后也可以分开.程序在运行之初就为该数据段申请了空间,在程序退出时才释放,因此,存储于数据段的数据的生存周期为整个程序运行过程.
(3)未初始化数据区.加载的是可执行文件BBS段,位置可以分开也可以紧靠数据段.程序在运行之初为该部分申请了空间,在程序退出时才释放,存储于该部分的数据的生存周期为整个程序运行过程.
(4)栈.由编译器自动分配释放.自动变量以及每次函数调用所需要保存的信息都存放在此段中.每次调用函数时,其返回地址以及调用者的环境信息都存放在栈中.然后,最近被调用的函数在栈上为其自动和临时变量分配存储空间.通过这种方式使用栈,可以递归的调用C函数.递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的变量集不会影响另一个函数调用实例中的变量.
(5)堆,通常在堆中进行动态存储分配.一般由程序员分配和释放,若程序员不释放,程序结束是由系统收回.堆位于非初始化数据段和栈之间.
图2 所示为ELF格式可执行文件存储结构和Linux进程基本结构的对照图.

图2 可执行文件与进程存储布局
3.为什么分这么多个区? (1)代码段和数据段分开,运行时便于分开加载,在哈佛体系结构的处理器将取得更好的流水线处理效率.
(2)代码是依次执行,由处理器的PC指针依次读入,而且代码可以被多个程序共享,数据在整个运行过程中有可能多次被使用,如果将代码和数据混合在一起将造成空间的浪费.
(3)临时数据及需要再次使用的代码在运行时放入栈中,生命周期短,便于提高资源利用率.
(4)堆区可以由程序员分配和释放,以便用户自由分配,提高程序的灵活性.
4.堆和栈的区别 栈是由编译器在程序运行时分配的空间,由操作系统维护.堆是由malloc()函数分配的内存块,内存的管理由程序员手动控制,在C语言使用free()函数完成.主要区别有一下几点:
(1)管理方式不同
程序在运行时栈由操作系统自动管理,无须程序员手工控制;而堆空间的申请、释放工作由程序员控制,容易产生内存泄露.
(2)空间大小不同
栈是向低地址扩展,是一块连续的内存区域.即栈顶的地址和栈的最大容量是系统预先规定好的,当申请的空间超过栈的剩余空间时,将出现栈溢出错误.堆是向高地址扩展,是不连续的内存区域.因为系统是用链表来存储空闲内存地址的,且链表的遍历方向是由低地址高地址.
(3)产生碎片不同
对于堆来说,频繁的malloc/free势必会造成内存空间的不连续从而造成大量的碎片,使程序效率降低.对于栈来说,一定是连续的物理内存空间.
(4)增长方式不同
在X86平台上,堆的增长方向是向上,即向着内存地址增加的方向;栈的增长方向是向下的,即向着内存地址减小的方向.
(5)分配方式不同
堆都是程序中由malloc()函数动态申请分配并由free() 函数释放;栈的分配和释放是由操作系统完成的,栈的动态分配有alloca()函数完成,但是栈的动态分配和堆是不同的,其由编译器进行分配和释放,无须手工完成.
(6)分配效率不同
栈是系统提供的,操作系统会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都是专门的指令执行.堆则是C函数库提供的,它的机制很复杂,例如为了分配一块内存,则需要操作系统重新整理内存,搜索整理内存空间,这样就有机会分到足够大小的内存,然后返回.显然,堆的效率比栈要低的多. 笔者:个人能力有限,只是学习参考...读者若发现文中错误,敬请提出.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------勿在浮沙筑高台,静下心来,慢慢地沉淀---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Linux程序存储结构与进程结构堆和栈的区别【转】的更多相关文章

  1. Linux程序存储结构与进程结构 堆和栈的差别

    摘要:本文主要讲述了Linux系统中.程序存储结构(代码区.数据段和BBS区)与进程的基本结构(代码区.数据段.BBS区.堆和栈).以及堆和栈的差别. Linux程序存储结构与进程结构 1.Linux ...

  2. 第二十一篇:Linux 操作系统中的进程结构

    前言 在 Linux 中,一个正在执行的程序往往由各种各样的进程组成,这些进程除了父子关系,还有其他的关系.依赖于这些关系,所有进程构成一个整体,给用户提供完整的服务( 考虑到了终端,即与用户的交互 ...

  3. Linux 操作系统中的进程结构

    前言 在 Linux 中,一个正在执行的程序往往由各种各样的进程组成,这些进程除了父子关系,还有其他的关系.依赖于这些关系,所有进程构成一个整体,给用户提供完整的服务( 考虑到了终端,即与用户的交互 ...

  4. [c++]堆和栈的区别

    堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构 ...

  5. 堆和栈的区别【zz】

    一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.2. ...

  6. <转> 堆和栈的区别

    一.预备知识—程序的内存分配    一个由C/C++编译的程序占用的内存分为以下几个部分    1.栈区(stack)—   由编译器自动分配释放,存放函数的参数值,局部变量的值等.其操作方式类似于数 ...

  7. 转载:C++中堆和栈的区别

    C++中堆和栈的区别,自由存储区.全局/静态存储区和常量存储区     文章来自一个论坛里的回帖,哪个论坛记不得了!    在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和 ...

  8. c++ 堆和栈以及区别

    c++中内存分成5个区:堆.栈.自由存储区.全局\静态存储区.常量存储区 栈是一种连续存储的数据结构,具有先进后出的性质.堆是一种非连续的树形存储数据结构,每个节点有一个值,整棵树是经过排序的,特点是 ...

  9. 20151024_001_C#基础知识(静态与非静态的区别,值类型和引用类型,堆和栈的区别,字符串的不可变性,命名空间)

    1:我们把这些具有相同属性和相同方法的对象进行进一步的封装,抽象出来类这个概念. 类就是个模子,确定了对象应该具有的属性和方法. 对象是根据类创建出来的. 2:类:语法 [public] class ...

随机推荐

  1. hibernate一对多注解

    package net.zmcheng.model; import java.util.HashSet;import java.util.Set; import javax.persistence.C ...

  2. 微信公众平台开发(112) 自动更新微信access token

    关键字:Memcache access_token 更新 存储 7200 本文介绍如何存储及更新 access token的方法. 一.Access Token access_token是公众号的全局 ...

  3. PHP加密解密字符串

    项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理. 最常见的应用在用户登录以及一些AP ...

  4. c3p0参数解释

    #最常用配置#initialPoolSize:连接池初始化时创建的连接数,default : 3,取值应在minPoolSize与maxPoolSize之间 c3p0.initialPoolSize= ...

  5. RFS_javascript的使用

    1. RFS对javascript的调用 (1)调用javascript语句 (2)调用javascript函数 2. IE8不支持javascript的 getElementsByClassName ...

  6. VS2013+qt-vs-addin-1.2.4安装配置

    --------------------------开头这部分可以跳过,仅作为笔记----------------------- 我问过的问题: http://www.codeproject.com/ ...

  7. css 正方体

    <!DOCTYPE html><html lang="zh-cmn-Hans"><head><meta charset="utf ...

  8. Java基础之创建窗口——使用流布局管理器(TryFlowLayout)

    控制台程序. FlowLayout把组件放在容器的连续行中,使每一行都放置尽可能多的组件.如果某行已满,就放在下一行.工作方式类似于文本处理器把单词放在行中.主要用途是放置按钮,但也可以用来放置其他组 ...

  9. mysql的binlog安全删除

    理论上,应该在配置文件/etc/my.cnf中加上binlog过期时间的配置项,expire_logs_days = 10 但是如果没有加这一项,随着产生越来越多的binlog,磁盘被吃掉了不少.可以 ...

  10. "数学口袋精灵"bug的发现及单元测试

    1.项目内容: 团队项目:二次开发 至此,我们有了初步的与人合作经验,接下来投入到更大的团队中去. 也具备了一定的个人能力,能将自己的代码进行测试.接下来尝试在别人已有的基础上进行开发. 上一界51冯 ...