计算机程序存储分配详解和c语言函数调用过程概述

版权声明:本文为博主原创文章,未经博主允许不得转载。欢迎联系我qq2488890051 https://blog.csdn.net/kangkanglhb88008/article/details/89667531

* 进程和线程的区别

        进程是操作系统分配资源的最小单位(比如分配的内存),而同一个进程内的线程共享这个资源。线程是系统分配时间片的最小单位。一个进程至少拥有一个线程。

* 程序与进程的区别

        进程是动态的(代码,数据,PCB控制卡组成,有一定的生命周期),程序是静态的(指令的集合)。一个程序可以对应多个进程,但一个进程只能对应一个程序。比如C语言编译程序,会对应的词法分析,语法分析,代码生成等几个独立的进程

* EIP寄存器,用来存储CPU要读取指令的地址,CPU通过EIP寄存器读取即将要执行的指令。每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加。

* 计算机内存芯片被分为3大块,栈区(存放局部变量,函数参数,当前状态,函数调用信息等,向地址减小的方向增长,所以是栈顶地址不变,新元素是从栈底不断进入的,所以栈底地址不断减小的,非常非常重要,可读可写可执行,都由系统自动动态的在这个栈内分配和释放),堆区(由程序员手动malloc函数分配然后free释放,向地址增大的方向增长,由链表实现的,可读可写可执行),全局区别名静态存储区,其中的变量常量在程序运行期间会一直存在,不会释放,程序结束后由系统释放。又可以分为两个小区,区1:存储初始化的全局变量和静态变量,可读可写不可执行;区2:未初始化的全局变量和未初始化的静态变量;区3(常量区):是否加了const修饰的,所有字符串常量也是存储在静态存储区(注:在单片机中,是否加了const修饰的字符串常量都是放在rom(flash)里面的,可能是因为单片机做了这样的存储优化,使得可以腾出全局区的内存来)),

代码段(冯诺伊曼体系计算机才存在),用来存放每个进程要运行的程序代码,这些代码是从外存里面拷贝进来的。如果是哈佛体系计算机,因为代码是存放在外存里面直接执行的,所以是不需要拷贝进入内存,那么内存中的这个进程也就不需要代码段了。

注:一个程序在编译时候是不会在内存中为它分配内存空间的,比如编译后的目标文件为obj.bin文件,此时只是根据全局声明时的类型进行占位,到以后程序即将执行时分配内存才会正确,比如现在这个程序.bin文件已经被从外存调入内存了(冯诺伊曼体系的计算机,程序都是被提前调入内存执行的),或者程序.bin文件就在外存硬盘或者flash里面执行(哈佛体系的计算机),现在这个程序即将开始执行,就会在内存中分配程序中声明和定义的所有全局变量了,已经初始化的全局变量就是被分配在全局区区1,而且根据obj.bin文件中的初值赋值,如果是未初始化的全局变量或者全部初始化为0的全局变量是被分配在全局区的2区的,就直接把这个区域全部赋值0就可以了(也就是说程序.bin文件里面就不会包含未初始化全局变量的初值信息了,这样也会让这个编译出来的.bin文件尽量小一些), 这就是为什么初始化的全局变量和未初始化的变量为什么要分区分配的原因,因为初始化方便。局部变量是程序运行起来了,在内存中的栈内动态的分配和释放的。

计算机外存(硬盘,flash芯片)分为两种文件

     1.普通文本文件和其他多媒体等等文件

     2.程序编译后的文件(程序代码区—存放函数体的二进制代码。)

这是一个前辈写的,非常详细 
//main.cpp 
int a = 0; 全局初始化区 
char *p1; 全局未初始化区 
main() 

int b; 栈 
char s[] = "abc"; 栈,这个过程是先在全局区分配了一个无名的字符串常量,然后把每一个字符单独赋给栈上定义的数组变量的每一个元素
char *p2; 栈 
char *p3 = "123456"; 123456\0在常量区,p3在栈上。 
static int c =0; 全局(静态)初始化区 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); 
分配得来得10和20字节的区域就在堆区。 
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 

关于C语言函数调用过程的栈变化详细过程请看我后续文章,因为知识比较多,单独写了一篇文章

猜你喜欢

转载自blog.csdn.net/kangkanglhb88008/article/details/89667531