第五章——内存和磁盘的亲密关系

思考问题

    1. 存储程序方式指的是什么   在存储装置中保存程序,并注意运行的方式  
      解析:现代计算机采用的是存储程序方式。
    1. 通过内存来提高磁盘访问速度的机制称为什么 Disk Cache(磁盘缓存)
      解析:磁盘缓存是指,把从磁盘中读出的数据存储在内存中,当该数据再次被读取时,不是从磁盘而是直接从内存中高速读出。
    1. 把磁盘的一部分作为假象内存来使用的机制称为什么 虚拟内存(virtual memory)   
      解析:借助虚拟内存,哪怕是内存容量不足的计算机,也可以运行很大的程序、
    1. Windows中程序运行时,存储着可以动态加载调用的函数和数据的文件称为什么?
      DLL(DLL文件)   
      解析:DLL是Dynamic Link Liabrary的略称
    1. 在EXE程序文件中,静态加载函数的方式称为什么
      静态链接  
      解析:函数的加载方式有静态链接和动态链接两种
    1. 在Windows计算机中,一般磁盘的1个扇区是多少字节
      512字节
      解析:扇区是磁盘保存数据的物理单位。

章节结构

  • 内存与磁盘的关系的:(磁盘上的程序)不读入内存就无法运行
  • 磁盘缓存加快了磁盘访问速度  
  • 虚拟内存把磁盘作为部分内存来使用
  • 节约内存的编程方法之让应用文件变小的两种方法
  • 磁盘的物理结构  

章节重点  

  • 内存和磁盘的异同点 
  • 相同点
  • 内存和磁盘都是具有存储程序命令和数据的功能。
  • 内存和磁盘也都是存储部件。    (计算机5大部件:输入设备、输出设备、存储器、运算器和控制器) 
  • 不同点
  • 内存利用电流来实现存储的,磁盘是利用磁效应来实现存储的。
  • 从存储容量来看,内存是高速高价,磁盘是低速廉价。
  • 本章中的内存和磁盘 本章中的内存主要是指主内存(负责存储CPU中运行的程序指令和数据的内存)。磁盘主要是指硬盘。

内存与磁盘的关系的:(磁盘上的程序)不读入内存就无法运行

存储程序方式(程序内置方式):程序保存在存储设备中,通过有序的被读出来实现运行。这一机制就被称为存储程序方式(程序内置方式)

磁盘中 存储的程序,必须需要加载到内存后才能运行,在磁盘中保存的原始程序是无法直接运行的

因为,负责解析和运行程序内容的CPU,需要通过内部程序计数器来指定内存地址,然后才能读出程序
即使CPU可以直接读出并运行磁盘中保存的程序,由于磁盘读取速度慢,程序的运行速度还是会降低

磁盘缓存加快了磁盘访问速度

内存和磁盘关系的一个例子。 磁盘缓存(disk cache):指的是把从磁盘中读出的数据存储到内存空间中的方式。

这样当接下来需要读取同一数据时,就不用通过实际的磁盘,而是从磁盘缓存中把内容读出。使用磁盘缓存可以大大改善磁盘数据的访问速度。

磁盘缓存提高访问速度的机制

    1. 首次读出时从磁盘读出(低速)
    1. 保存读出的数据(作为内存的一部分)
    1. 再次读取同一数据时从内存读出(高速)

把低速设备的数据保存在高速设备中,需要时可以直接将其从高速设备中读出,这种缓存的方式在其他情况也会用到,如web浏览器中。

虚拟内存把磁盘作为部分内存来使用 虚拟内存磁盘缓存这是两个相对的概念。

  • 虚拟内存是把磁盘的一部分作为假想的内存来使用,(实际上是磁盘)
  • 磁盘缓存是把内存的一部分作为假想的磁盘来使用,(实际上是内存)

通过借助虚拟内存,在内存不足时,也可以运行程序。 但是要牢牢记住一点CPU只能执行加载到内存中的程序
虚拟内存虽然是把磁盘作为内存的一部分来使用。但实际上正在运行的程序部分,在这个时间点上是必须存在在内存中的
为了实现虚拟内存,就必须把实际内存(也可称为物理内存)的内容,和磁盘上的虚拟内存的内容进行部分置换(swap),并同时运行程序。

整段话的意思是,CPU只能执行加载到内存中程序,而内存有限。

所以可以把程序不当做一个整体,而看成是很多部分组成,在需要执行哪个部分时就把它存储到内存中,而其他部分则在磁盘中专门开辟个空间用于存放这些部分。

因此从程序整体的角度来看,运行的程序一部分存储在内存上,一部分存储在磁盘上专门开辟的空间(这部分空间就叫做虚拟内存)。

从微观角度来看,程序是由各个部分组成的,正在运行的那部分还是存储在内存上,符合CPU只能执行加载到内存中程序”的要求。同时通过“部分置换”,不断把需要后续部分置换进来,而已经运行过的部分置换出去

虚拟内存的方式(两种)

  • 分页式 分页式:该方式是指,在不考虑程序构造的情况下,把运行的程序按照一定大小的也(page)进行分割,并以页为单位在内村和磁盘间进行置换。

在分页式中,把磁盘的内容读出到内存称为Page In
把内存的内容写入磁盘称为Page out

需要运行的部分就Page In,不需要运行的部分就Page Out。

windows采用分页式,一般,Windows计算机的页的大小是4KB。也就是把大程序用4KB的页来进行切分,并以页位单位放入磁盘(虚拟内存)或内存中。

为了实现虚拟内存功能,Windows在磁盘上提供了虚拟内存用的文件(page file,页文件)。该文件由Windows自动做成和管理

文件的大小也就是虚拟内存的大小。通常是实际内存的相同程度至两倍程度。

  • 分段式
    分段式虚拟内存是指,把要运行的程序分割成以处理集合及数据集合等位单位的段落,然后再以分割后的段落为单位在内存和磁盘之间进行数据置换。

虚拟内存的缺点

虽然通过借助磁盘虚拟内存就可以解决内存不足的问题。而虚拟内存也确实能避免因内存不足导致的应用无法启动。

不过,由于使用虚拟内存时发生的Page In和Page Out往往伴随着低速的磁盘访问,因此在这个过程中应用的运行会变得迟钝起来,可能会导致应用一时无法操作。

节约内存的编程方法之让应用文件变小的两种方法

解决内存不足的问题:上面通过虚拟内存的方法,但是也有种种缺点。
为了从根本上解决内部才能不足的问题:要么增加内存的容量;要么尽量把运行的应用文件变小
将运行的应用文件变小的两种方式:通过DLL文件实现函数共有通过调用_stdcall来减小程序文件的大小

通过DLL文件实现函数共有

DLL文件,是在程序运行时可以动态加载Library(函数和数据的集合)的文件。(DLL,Dynamic Link Library)
多个应用可以共有同一个DLL文件。通过共有同一个DLL文件则可以达到节约内存的效果

DLL文件的两个优点

  • 通过共有同一个DLL文件可以节约内存
  • 比如在Windows中在不变更EXE文件的情况下,通过升级DLL文件就可以更新

通过调用_stdcall来减小程序文件的大小

通过调用_stdcall来减小程序文件的方法,是用C语言编写程序时可以利用的高级技巧。这一思路也可以用在其他编程语言中。

_stdcall 是standard call(标准调用)的略称。Windows提供的DLL文件内的函数,基本上都是_stdcall调用方式,采取这种调用方式主要是为了节约内存。

另一方面,用C语言编写的程序内的函数,默认设置都不是_stdcall。
因为C语言对应的函数的传入参数是可变的(可以设定任意参数)
只有函数调用方才能知道到底有多少个参数。而这种情况下,栈的清理作业便无法进行。 不过,在C语言中,如果函数的参数数量固定的话,指定_stdcall是没有任何问题的。

这段话的意思是C语言默认的函数调用方式中,栈清理处理指令是作为函数调用方的一部分,每调用一次函数,就在函数调用方的函数调用语句后面添加该指令,调用几次就在函数调用方那里添加几次

这种处理机制会导致函数调用方随着函数调用次数的增多,而变得越来越臃肿。此时就可以使用 _stdcall方式调用函数,这种调用方式,会在被调函数方中添加栈清理处理指令

C语言中,在调用函数后,需要执行栈清理处理指令

栈清理处理是指,把不需要的数据从接受和传递函数的参数时使用的内存上的栈区域中清理出去。
栈清理处理不是程序记述的,而是在程序编译时,由编译器默认将该处理附加在函数调用方。

CPU会提前准备好栈机制。往栈中存储数据的汇编语言指令是push。从栈中取出数据的汇编语言指令是pop。栈一般是用来实现函数调用机制的

举个例子

// 函数调用方
// main函数调用了函数MyFun();
void main()
{
	int a;
	a = MyFunc(123,456);
}

// 被调用方
int MyFunc(int a,in b)
{
	....
}

函数main()调用了函数MyFun()。
按照默认设定,栈的清理处理会附加在函数main()这一方。
在同一个程序中,同样的函数可能被多次反复调用。而如果是同样的函数,栈清理处理的内容也是一样的。由于该处理实在调用函数乙方,因此就会导致同一处理被反复进行。这就造成了内存的浪费。

// 调用函数MyFunc()的部分用汇编语言表示
push 1C8h   // 将参数456(=1c8h)存入栈中
push 78h  // 将参数123(=78h)存入栈中
call sLTD+15 (MyFunc)(00401014)  // 调用MyFunc()函数
add esp,8 // 运行栈清理

C语言通过栈来传递函数的参数。

  • 第一步,push 1C8h和push 78h

push是往栈中存入数据的指令。 32位CPU中,1次push指令可以存储4个字节的数据。
上面代码中,由于使用了两次push指令把两个参数(456和123)存入到了栈中,因此总的来说就是存储了8字节的数据

  • 第二步,call sLTD+15 (MyFunc)(00401014)

通过call指令调用函数MyFunc()后,栈中存储就不再需要了。

  • 第三步,add esp,8 // 与pop指令有相同功能

通过add esp,8这个指令,使存储着栈数据的esp寄存器前进8位(设定为指向高8位字节地址),来进行数据清理。

CPU 中,占中堆积的最高位的数据地址是保存在esp(esp是Pentium系列CPU的栈指针名)中。连续运行两次pop指令,可以消除第一步中两个存储在栈中的4字节数据,而同样的功能也可以通过esp的数值加8来实现。

使用默认方式和_stdcall两种方式

站清理处理,比起在函数调用方进行,在反复被调用的函数一方进行时,程序整体要小一些。这时所使用的的是_stdcall。
在函数前加上_stdcall,就可以把栈清理处理变为在被调用函数一方进行。 程序大小因此会减小。

磁盘的物理结构

磁盘是通过其物理表面划分成多个空间来使用的。划分的方式有扇区方式可变长方式两种。

扇区方式

扇区方式:将磁盘划分为固定长度的空间。

一般的Windows计算机所使用的硬盘和软盘,采用的都是扇区方式。

磁道:扇区方式中,把磁盘表面分成若干个同心圆的空间,这些别成为磁道
扇区:把磁道按照规定代销(能存储的数据长度相同)划分而成的空间就是扇区 扇区是对磁盘进行物理读写的最小单位。

Windows中使用的磁盘一般1个扇区是512字节。
windows 在逻辑方面(软件方面)对磁盘进行读写的单位是
簇是扇区的整数倍
根据不同的磁盘容量,1簇大小也会不同 1簇 =1扇区 = 512字节
1簇 =2扇区 = 1KB
......
1簇 =64扇区 = 32KB
磁盘的容量越大,簇的容量也越大
不管多小的文件,都会占用1簇的空间 windows中文件最小位512字节的由来,以及文件没有513字节大小的原因就在于此。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部