嵌入式Linux与物联网软件开发:C语言内核深度解析
上QQ阅读APP看书,第一时间看更新

1.3 位、字节、半字、字的概念和内存位宽

1.3.1 深入了解内存(硬件和逻辑两个角度)

在前面我们就已经介绍了什么是内存,这里我们继续深入理解内存。

从硬件角度,内存实际上是电脑的一个配件(一般叫内存条)。根据不同的硬件实现原理,还可以把内存分成SRAM和DRAM(DRAM又有好多代,如最早的SDRAM,后来的DDR1、DDR2、LPDDR……)。

从逻辑角度:内存可以随机访问(随机访问的意思是只要给一个地址,就可以访问这个内存地址),并且可以读写(当然了,逻辑上也可以限制其为只读或者只写)。内存在编程中的本质是用来存放变量内容的(就是因为有了内存,所以C语言才能定义变量,C语言中的一个变量实际就对应内存中的内存空间)。

1.3.2 内存的逻辑抽象图(内存的编程模型)

对于编程者来说,不需要深入了解内存的电子结构,但是内存的逻辑结构是必须知道的。从逻辑角度来讲,内存实际上是由无限多个内存单元格组成的,每个单元格有一个固定的地址,叫内存地址,这个内存地址和这个内存单元格唯一对应且永久绑定。

为了大家更好地理解,我们以大楼来类比内存。逻辑上的内存就好像是一栋大楼,内存的单元格好比大楼中的一个个小房间,每个内存单元格的地址就好象每个小房间的房间号。内存中存储的内容就好像住在房间中的人。如果我们想要找到一个人和他说点什么,那么我们就必须知道他的房间号。同理,我们对内存中某个空间操作,前提是我们需要知道它的内存地址。C语言虽然不像汇编、可以写出直接操作内存的指令,但本质的东西是不会变的,内存的硬件构造是不会变的。你不告诉CPU内存地址,CPU就无法控制指令将数据读写到正确的内存空间。所以C语言也不例外,虽然C语言并不会直接操作内存地址,但变量的引入其实就是对内存的操作。在下面左图中,我们给出了一个内存条的逻辑模型,内存地址的排列是从零开始。右图的目的是为了让大家明白,除了内存条还有其他硬件设备也有内存,像显卡内存、网卡内存,但在CPU看来它们和内存条并无二异,只要有地址就可以控制数据的读写。

8位内存模型

其他具有内存的硬件

逻辑上来说,内存可以有无限大,因为数学上编号是没有尽头的。但是现实中实际的内存大小是有限制的,如32位的系统(32位系统指的是32位数据线,但是一般地址线也是32位,这个地址线32位决定了内存地址只能有32位二进制,所以逻辑上的大小为2的32次幂),内存限制就为4G。实际上32位的系统中可用的内存是小于等于4G的(如32位CPU装32位Windows,但电脑实际可能只配置了512MB内存条)。这里涉及三总线的概念。所谓三总线就是指地址总线、数据总线和控制总线。如我们现在要向内存中写入一个数据,这个过程就是,控制总线上面传输写指令,地址总线上面传输内存地址,而数据总线传输要写入内存的数据。由此可知总线的重要性。我们常常讲多少位CPU,指的就是数据总线位数。数据线越多,一次传输处理的数据就越多,性能也就越好,这也是为什么32位的CPU就比16位的性能强。

地址线的数量决定了它可以寻址内存空间的大小。我们举个简单例子,例如我们有两根地址线,每根地址线上面可以传输0或者1,那两根线就有4种不同的状态,分别是00、01、10、11。由这4种不同的状态就可以确定4个地址。如果有32根地址线可以确定多少种不同状态?2的32次方,也就意味着最高可访问的内存大小为2的32次幂(4G)。

内存的逻辑结构

1.3.3 位和字节

上面讲了内存不可能无限大,那么为了衡量内存大小以及更好地使用内存,我们就需要引入内存单位。内存单位有很多,我们平时经常提到的以G为单位的内存,其实对于编程来说,这个单位反而不常用。我们编程往往是操控内存单元。下面首先给出一个单位换算表达式。

1GB=1024MB 1MB=1024KB 1KB=1024B 1B=8bit

这里的KB是千字节的意思。注意,计算机里面的千是1024,而不是1000。B是字节(Byte), bit是位(bit),也叫二进制位,可见它是表示二进制的一位(0或者1),我们的代码和数据编译后对应的就是二进制的0和1。除了我们了解的位(1bit)、字节(8bit),还有半字(一般是16bit)、字(一般是32bit)。这里我们特别注意,在所有的计算机中,不管是32位系统、16位系统,还是以后的64位系统,位永远都是1bit,字节永远都是8bit。

1.3.4 字和半字

历史上曾经出现过16位系统、32位系统、64位系统等,而且操作系统还有Windows、Linux、iOS等,所以很多的概念在历史上的定义都很乱。建议大家对字、半字、双字这些概念不要详细区分,只要知道这些单位具体是多少字节,都是依赖于平台的。实际工作中,我们了解了这些平台后,才具体到该平台的“字”是多少位,当然“半字”永远是字的一半,双字永远是字的两倍大小)。编程时一般用不到“字”这个概念,我们区分这个概念主要是因为有些文档中会用到这些概念,如果不加区别可能会造成对程序的误解。

1.3.5 内存位宽(硬件和逻辑两个角度)

内存位宽(内存数据线的数量)是指在一定时间(时间指的是一个时钟周期,不需要了解)内所能传送数据的位数,位数越大,则所能传输的数据量就越大。左图就是一个8位的内存逻辑图,右图是32位的内存逻辑图。8位内存模型表示一次可以传送数据的位数为8位,32位内存模型表示一次可以传送数据的位数为32位,所以我们把32位(4个格子)画为一排,学了下面的内存编址你就会更加明白了。

从硬件角度讲:硬件内存的实现本身是有宽度的,也就是说有些内存条就是8位的,而有些就是16位的。那么需要强调的是,内存芯片之间是可以并联的,通过并联,即使8位的内存芯片也可以做出来16位或32位的硬件内存。

从逻辑角度讲:内存位宽在逻辑上是任意的,甚至逻辑上存在内存位宽是24位的内存(但是实际上这种硬件是买不到的,也没有实际意义)。不管内存位宽是多少,对操作不构成影响。但是因为操作不是纯逻辑而是需要硬件去执行的,所以不能为所欲为,我们实际上很多操作都是受限于硬件的特性。如24位的内存逻辑上和32位的内存没有任何区别,但实际硬件都是32位的,都要按照32位硬件的特性和限制来编程。