OC学习日记Day3:数据在内存的储存形式,CPU查找内存数据
要点说明:
a.理解数据以什么样的形式存储在内存当中。
b. 系统是怎么划分内存,怎么组织内存。
c. CPU是根据什么找到内存的数据
1. 数据,数据在哪里?
现在我们了解一个概念:8GB。这里的G是一个数量单位。1G=1024M、1M=1024K、1k=1024。那么1G=1024*1024*1024=1073471824。这里的B是指字节,一个字节表示8个位。请注意,“位”才是我们关注的重点!你完全可以把位这个概念理解成一个格子。一个存储信息的格子。在电脑的世界里,它所能识别的字母就是0和1。对于格子(位)来说,格子里放满电,就是1、放空电,就是0。综上可知,一条8GB的内存条一共有8*1073471824*8个格子。那么数据是怎么存储到这些格子里面的呢?
我们在日常生活中,常用是十进制计数。可是电脑的世界只有0和1,所以它们使用的是二进制。但就算它们使用的二进制,也无法阻止电脑理解现实世界的步伐。这里我们以数字15为例,电脑为了识别“15”这个数字,向内存要了4个格子XXXX。本着满二进一的原则将“15”填进这4个格子里,填完之后这四个格子就变成了1111。也就是把这四个格子全放满电。同理,表示数字“13”可以是1101,数字“10”可以是1010等。对于数字如此,对于字符也是如此。例如26个字母,电脑可以向内存要5个格子,用00000表示字母A 、00001表示字母B,这样一直推到字母Z。(这里只是为了解释方便一点,所以描述字符只用了5个格子,其实字符编码远比我这里描述的复杂。如果读者想要深入了解这部分内容,可以问问度娘或者留言告诉我有多少人想了解,如果想知道的人多我就详细讲解一下)
总上可知,在电脑的世界虽然只有0和1两个字母,但它完全可以通过多格子的组合去表示整个现实世界的所有信息。即是我们数据是通过一组一组内存中的格子组合表示出来的。这里我们知道了数据是怎么存在内存中了(就是将数据分解成一组格子,以每个格子0或1的序列存储)。
2. 内存,内存要听话!
前面我们提到过,程序是存放在内存当中,供CPU执行时使用的。这里的程序指的可不仅仅是指一个应用,而是指整个系统。当电脑启动时,需要将硬盘中的整个系统程序传到内存中,以供CPU将整个系统执行起来,而应用程序是建立在操作系统的基础上的。我们可以把内存想象成一个世界,一个模拟世界。内存里面的每一个格子都是这个世界的可用资源。而操作系统便是这个模拟世界的最高执政机构,它本身的存在需要占用一部分资源,但它的主要任务是管理和分配这些内存资源,让每一位人民(应用程序)都能享受到足够的内存资源。如果操作系统管理内存资源不妥当,造成一部分人民(应用程序)占有大量内存资源,而其他人民(应用程序)却无法得到满足其生存的内存资源,那么这个世界总是会充满抢夺内存的战乱。这也是为什么使用某些操作系统总比另一些操作系统流畅的原因。内存资源管理是重要关键之一。额,没有之一。
为了理解系统怎么管理和分配内存的,我做了一张示意图,如下:
在系统内存区域,是操作系统工作的地方。操作系统以此为基础,管理着整个内存资源。在这个图当中,我们主要关注的点是应用内存区域。在应用内存块里面:
静态区是程序编译的时候就已经分配好了,通常放静态数据和全局数据。
函数代码区域是放函数代码二进制文件的区域。
栈内存区是存放程序的参数值和局部变量值的区域。
堆内存区是给程序员自由发挥的内存区域,判断一个程序员溜不溜的标准便是看这个程序员怎么利用这部分内存资源了。
字符常量区是给存放一些使用频率较高的字符常量。避免系统创建大量重复的字符常量而浪费内存资源。
3. CPU怎么找朋友?
CPU执行的数据是从内存区域里面取出来的,现在问题是内存里面有那么多格子,CPU怎么准确地找到所要的数据呢?在我们使用地图去查找某个地方的时候我们根据的是这个地方的地址。而CPU查找内存中的数据的时候也是根据内存的地址去查找的。对于一个8GB的内存区域来说,我们为这条内存分配了8G个地址,每一个地址对应着一个B(也就是一个字节,一个字节里面有8个格子(位))。这样CPU就可以从4G个地址里面找到内存区域里面的所有数据了。
这里又出现了一个问题,CPU是怎么快速查找这些地址的?8G这个数量是非常大的(1G=1073471824),CPU不可能每一次查找数据都要向每一个地址问一问:你是不是我要找的数据呀?为了解决这个问题,我们换一个角度去思考。不要让CPU自己去找数据了,让数据自己去找数据,让数据自己告诉CPU下一个数据存放的地址,这样CPU就可以直接根据这个地址去找到数据了。这样,CPU就不用瞎忙活着找数据了。
这样,每当我们要启动一个应用程序,操作系统就告诉CPU这个应用程序的首地址在哪里。然后CPU就把这个地址的数据取出来,但这个数据处理完成之后,这个数据又告诉CPU下一个数据的地址,这样告诉地址、取数据、处理数据、告诉地址反复循环,直到用户退出这个应用程序,退出整个系统。到此,也可以解释为什么我们的应用程序总要有一个启动的起点,不管是main函数,还是自定义的其它函数。它们终归就是一个作用:告诉操作系统,把我的地址传给CPU,就可以启动这个应用程序了。