转自: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. Winform项目调用asp.net数据接口

    最近一个WPF项目需要改写成android项目,思路是在asp.net项目中编写一个通用接口,便于其它平台下调用数据.刚接触到这些东西的时候完全是一头雾水,最根本的原因是不明白网站中的一个网页,为什么 ...

  2. ipmi使用

    1.安装ipmitool Linux: yum -y install OpenIPMI-tools 备注:Linux机器也可以安装ipmi  yum -y install OpenIPMI OpenI ...

  3. button点击传多个参数

    // --------------------button点击传多个参数------------------------ UIButton *btn = [UIButton buttonWithTyp ...

  4. 阿里云的ubuntu server 12.04 下安装jdk和tomcat

    因为想自己在做个简单粗暴的小游戏,弄到朋友圈去,买了个阿里云服务,当时选的的ubuntu sever 12.04的os,恰巧朋友又委托一个小项目,所以先尝试搭建下环境. 首先,用putty或者SSH ...

  5. 当AS3遇见Swift(一)

    当AS3遇见Swift 从Hello开始 As3 trace(“Hello Eko”) Swift println(“Hello Eko”) 挺象,有点隔壁王叔叔的意思. 常量和变量 As3 publ ...

  6. PostgreSQL pg_dump pg_dumpall and restore

    pg_dump dumps a database as a text file or to other formats. Usage: pg_dump [OPTION]... [DBNAME] Gen ...

  7. SQL 数据库 连接查询 变量、if else、while

    一.连接查询:通过连接运算符可以实现多个表查询. 连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志. 常用的两个链接运算符: 1.join   on(左右连接) 2.uni ...

  8. int和long long有符号整形 负数比正数多一个

    int的负数比正数多一个,则有一个负数在int范围内没有对应的正数 最大正整数用十六进制,很容易表示:0x7f ff ff ff int num = 0x7fffffff; num = -num; p ...

  9. [转] HashMap和HashSet的区别

    HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题不涉及到HashSet和H ...

  10. android 内存不足的问题

    FAILURE: Build failed with an exception. * What went wrong: A problem occurred configuring project ' ...