关闭

从几个角度谈谈内存的管理和划分

标签: 内存
137人阅读 评论(0) 收藏 举报
分类:

1.从操作系统的角度

操作系统管理内存是作为开发者认识内存最基本的起点,对于windows 操作系统是通过对内存分页划分和管理的(Windows一个分页是4KB),这是为了让操作系统很快的寻址和管理。当然对于分页的寻址和回收也有自己各种各样的算法,每款系统都有自己的算法,这里就不多讲了(你可以在其他资料上面看到关于不同系统对于内存的管理,回收的原理和算法)。一般内存加载系统之后,系统占有的部分和应用占有分配的内存空间是独立分开的,除非应用调度系统的资源。

2.栈

对于程序员而言,听到栈应该是很多的,但是是不是很是理解呢?

首先要知道栈是什么样的数据结构 -- 顺序结构,或者是存储序列,只是先压栈最后弹栈罢了。(堆是链表,不连续的)

一般在栈里面存储的数据是基本数据类型(int char double 等)和 指针句柄类型。

栈一般不是程序员(开发者)控制的,它是编译器或者系统分配的,那么如果是编译环境控制的,我们认为能不能在编译环境设置或者编码设定呢?那么这要具体根据开发环境了或者说开发语言支不支持。对于 Windows一般分配的栈是2M。对于c#开发语言,我们可以在vs环境里面设置(#param comment clinker,"stack": 10000000   10M),但是对于c、c++语言我没有了解过是否支持设置。

对于Android系统eclipse 我也没有看到设置栈的大小的资料,可能是不支持。Android系统对于2.0x版本分配给应用UI线程的栈大小是8kb,4.0x是16kb,注意这里是UI主线,包含视图句柄和其他的数据。其他的线程可能还要分配的栈空间,这些栈空间加在一起就是虚拟机对应用分配的栈空间,或者系统对虚拟机分配的栈空间(每个应用就是跑起来的虚拟机)。

3.堆

它才是我们程序员天天打交道的东西,我们有权对其开发和回收。(尤其是面对对象编程,每一个对象几乎都是放在堆上面 "new 出来")

堆是链表结构,不是连续的。

在堆上面可以存储全局变量或者对象(对象包含自己的成员变量和方法)

当然不同的系统 对堆的限制也不一样,对于Android系统而言貌似是限制在256M,对于Windows系统貌似只要你的内存够大,你可以随意的开发。

4.静态存储区

static声明的变量或者方法或者常量

和系统没有什么关系,系统不关心什么static,只是编译器关心的,要么自己搞一个static区域或者直接在堆中保存。因为有的语言在编译的过程中,直接将static存储在堆,没有所谓的static区域,只是其生命周期是伴随整个应用。

5.常量区

即常量的保存区域

和系统没有什么关系,系统不关心什么常量,只是编译器关心的,要么自己搞一个常量区域或者直接在堆中保存。因为有的语言在编译的过程中,直接将常量存储在堆。


还有一个概念--代码区

6.代码区

也许很人也听说这个名词,其实这个概念就不涉及什么内存的划分,这个概念应该是操作系统的东西。

我们知道开启一个应用,对于系统而言就是创建一个进程,(进程里面可能包含一个或者在多个线程,那就看你的应用是多线程的还是多线程的)进程是由三部分组成:sp,pcb和代码区。pcb是程序控制模块,sp是指令计数器,代码区就是这个应用要执行的指令和数据,换句话说就是你具体要干的什么事。代码区的数据和指令就是要在栈和堆里面创建的数据和执行的指令。

如果你开好几个应用,并行执行,比如你在听歌又在敲代码,那么属于不同进程的多线程,CPU在不同的时间片上切换不同的线程(时间片20ms).

注意:同一进程的多线程之间可以共享数据,但是不同进程中的线程不能共享数据


上面所说的似乎阅读起来是从系统方面和编译器方面对内存管理做了角度叙述,但是说回来,编译环境对内存进行划分还是基于系统的,所以本质上还是系统对内存进行的划分。之所以上面这样划分形式的阐述是为了加强一个应用从诞生的角度(编码)理解内存和相关数据的生命周期。

系统起一个进程,分配了内存空间,进而也会更细化的对线程数据和指令存储进行划分,这进一步的划分是根据生命周期和作用域。

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:31198次
    • 积分:1889
    • 等级:
    • 排名:千里之外
    • 原创:156篇
    • 转载:34篇
    • 译文:1篇
    • 评论:10条
    最新评论