进程内存使用

进程运行必须占用内存,运行之前就已定义好的即为静态分配,运行时分配的便是动态分配。

5种类型:

1. 代码段 .text 

    存放指令代码,属性为只读。很多人不理解为什么哈弗结构既然是 .text 和 .data 分离,那只有一个RAM ,怎么解释呢,其实这很简单啊,IA32不是有选择子么

   数据段有数据段的选择字,有数据段的属性,代码段有代码段的属性,有它的选择字,ARM 也无非就是将段分成不同的属性来管理,一个介质RAM搞定。

2. 数据段 .data

    存放已初始化数据,这个真没啥好说的。

3. BSS段  .bss

    存放未初始化全局变量,由此一同事问我,为什么BSS不需要占用 img大小,我想了想,诶,这肯定不占用啊。因为BSS不要像.data 那样有image 数据啊。

  如果不明白,可以这么想,既然是未初始化的数据,那么数据原本就是未知的,那么就没有必要保存这个初始化数据了。

    例如  

    static  int i = 0x12345678;         /* 这里0x12345678保存在可执行镜像 img 文本内 */

    static  int j ;                /* 没有任何的img 数据 */

    void x (void) 

    {

        printf ( "%d%d \n",i,j);      /* 那么取 j 的时候,就只管在内存中 *(&j) 咯 */

    }

  虽然是这样,但是未初始化的变量容易出问题,所以很多时候我们必须要清零 bss区,将所有用户”未初始化“数据,初始化一遍,这就是 main 函数前所做的事情了。

4. HEAP 堆

 动态分配,往高地址扩展,malloc ,则地址增,free 则地址减。

5. 栈 STACK

 又被称作临时数据交换区

 在IA(x86)里面,

   int a [4];

   那么相应的汇编即为  SUB   ESP  4 * 4 ; 这里是4个 int 就是 4*4字节;

   在ARM 里面就是   

   int  a [4]; 

 汇编就是   SUBS  R13,R13,#4*4  ; R13 通常为堆栈指针,仅仅是通常哈!

   那么存放的数据是怎么放进去的? 答案是代码里嵌入进去的,比如 堆栈   int  a  = 0x1234 ,那么在创建堆栈之后,就是   mov  [xxxx],0x1234。

   函数call / bl 完一般有一个 add(s) ,清除堆栈,因此,如果函数呼叫完,还访问堆栈的数据,不一定是不正确的,但是绝对是不安全的。注意这点就好。

   这里还有一个小问题,那就是C 和 ASM 混合使用的时候,C呼叫 ASM 函数,或者 ASM 呼叫 C函数,这里的堆栈使用就很有乐趣了。这涉及到堆栈平衡的问题

 在嵌入式里面非常有用的一点就是C呼叫ASM函数了

   比如在 asm 里面 push   0x11111111

            push  0x222222222

            push  0x333333333

            call   xxx

            add  esp,0x0C

   但是在C 函数xxx ()里可以不一定要写全3个参数,这样我们可以有选择的取参数。

   这在ARM 里面非常有用,(ARM 默认 R0 - R3作为前4个参数)

 那么在 asm 里面 LDR  R0,=0x11111111

          LDR  R1,=0X22222222

          LDR  R2,=0X33333333

          LDR  R3,=0X44444444

          BL  xxx

SUM :进程内存使用分布图

 

posted @ 2013-10-13 17:46  moon_cat  Views(271)  Comments(0Edit  收藏  举报