《程序是怎样跑起来的》(中)
学习笔记
第4章 熟练使用有棱有角的内存
本章提问
#### 本章重点 对内存要有物理上和逻辑上的认识。
##4.1 内存的物理机制很简单 内存实际上是一种名为内存IC的电子元件,包括DRAM,SRAM、ROM多种形式。 ![内存引脚配置示例](https://upload-images.jianshu.io/upload_images/17108100-7b452cb7ac71f0b3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 内存可以存储多少数据? 数据引脚有D0~D7共8个,一次可以输入输出8位(1字节)的数据,地址信号有10个,即可表示1024个不同地址,所有内存可以存储1024字节,即1KB的数据。 实际计算机中,会有更多的地址信号引脚,可以存储更多的数据。 内存的读写,改变控制位WR、RD,指定地址即可。 ![内存读写](https://upload-images.jianshu.io/upload_images/17108100-cfa7e9247222e1ac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##4.2 内存的逻辑模型是楼房 数据类型不同,占用内存大小不同。 ![1KB内存的模型](https://upload-images.jianshu.io/upload_images/17108100-83e6164ade384eeb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![数据类型不同,占用内存不同](https://upload-images.jianshu.io/upload_images/17108100-5bb10d6de625e5e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##4.3 简单的指针 指针也需要指定数据类型,数据类型表示从指针指向的内存中一次性读取的字节数。 ![](https://upload-images.jianshu.io/upload_images/17108100-ab57b45ff20122aa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 假设d、e、f都是一百,则使用三个指针从地址为100的内存中读取的字节数不同: ![指针的数据类型表示一次可以读写的长度](https://upload-images.jianshu.io/upload_images/17108100-ce70375ec45d82be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 4.4~4.7 略
#### 问题答案 ![答案](https://upload-images.jianshu.io/upload_images/17108100-b293f9097dca930a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# 第5章 内存和磁盘的关系 #### 本章问题 ![问题](https://upload-images.jianshu.io/upload_images/17108100-d450672de4cbc8ca.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##5.1 不读入内存就无法运行 ![程序要加载到内存之后才能运行](https://upload-images.jianshu.io/upload_images/17108100-8cfe516e4bb36cde.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##5.2 磁盘缓存加快了磁盘访问速度 磁盘缓存指的是把从磁盘中读取的数据存储到内存的一种方式,可以加快数据的访问速度。 但是随着现在磁盘能力的提升,磁盘缓存的作用已经没有那么明显了。
##5.3 虚拟内存把磁盘作为部分内存来使用 为了实现虚拟内存,必须把实际内存同虚拟内存进行部分置换,并同时运行程序。
##5.4 节约内存的编程方法 两种方法。 #####第一种方法:通过DLL(Dynamic Link Library,动态链接库)文件实现函数共有 比如有两个应用程序都包含了一个同样的函数:![静态链接](https://upload-images.jianshu.io/upload_images/17108100-fa1c0584539277d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 两个应用可以通过DLL文件共有这个函数,从而节约了内存: ![动态链接](https://upload-images.jianshu.io/upload_images/17108100-01dc7ab6764bc8bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) #####第二种方法,通过调用_stdcall来减少程序文件大小 ![关于stdcall](https://upload-images.jianshu.io/upload_images/17108100-c82f98d71af6d33d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) C语言中,调用完函数需要进行栈清理,比如从main()中调用MyFunc(),按照默认设定,栈清理会附加在main()一方,如果反复调用就会反复清理,造成内存浪费。如果用_stdcall把int MyFunc(int a)变为int _stdcall MyFunc(int a),栈清理就会在MyFunc一方执行,清理一次即可。
##5.5 磁盘的物理结构 一般有扇区方式、可变长方式两种,前者长度固定,后者反之。Windows采用扇区方式。 一般一个扇区是512字节,簇是扇区的整倍数,即n扇区。 不同文件不能存储在同一个簇中,不管多小的文件,最少占用一个簇的空间。 如果簇的容量设定过小,那么文件读写就会变慢,如果过大,就会浪费存储空间。所以,簇的大小,是由处理速度和存储容量的平衡来决定的。
#### 问题答案 ![答案](https://upload-images.jianshu.io/upload_images/17108100-319f61f9bf95cbf6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#第6章 亲自尝试压缩数据 #### 本章问题: ![问题](https://upload-images.jianshu.io/upload_images/17108100-4026c15520c57b46.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##6.1 文件以字节为单位保存 ![文件是字节数据的集合体](https://upload-images.jianshu.io/upload_images/17108100-e9bd4473f280caa2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##6.2 RLE算法的机制 即字节×重复次数 ![RLE](https://upload-images.jianshu.io/upload_images/17108100-1ef4eb503d6762ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![关于RLE](https://upload-images.jianshu.io/upload_images/17108100-6156498ec73a043a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##6.3 RLE算法的缺点 此书作者曾对不同文件做过RLE实验,结果如下: ![](https://upload-images.jianshu.io/upload_images/17108100-ae6aa1bfbe8b3dbb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 可以看出,文本文件的压缩率不降反增,那是因为文本文件中出现重复字符的几率比较小,加入的重复次数反而占据了更多了存储空间。我们可以想办法进行改进,比如不统计单个字符的重复字数,而统计单词的重复次数等等。
##6.4 通过摩尔斯编码来看哈夫曼算法的基础 哈夫曼编码的关键就是“常用的字符用较少的比特表示,不常用的字符可以用较多的比特表示”,但要注意不管满不满8个比特,最后都要以8个比特存储在内存中(如下图),这会使程序变得复杂,但是压缩率也会高不少。 ![](https://upload-images.jianshu.io/upload_images/17108100-cef68176d9700ee6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 摩尔斯电码就不说了。
##6.5 用二叉树实现哈夫曼编码 摩尔斯电码的编码体系是固定的,而哈夫曼为不同的压缩对象构建不同的编码体系。 ![用哈夫曼压缩的文件构造](https://upload-images.jianshu.io/upload_images/17108100-70c6dd4bb4ea0f77.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 以AAAAAABBCDDEEEEEF为例: ![编码方案](https://upload-images.jianshu.io/upload_images/17108100-d252eb8ae4162709.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![构造哈夫曼树](https://upload-images.jianshu.io/upload_images/17108100-58d8018a9b5ae50e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 哈夫曼不用在字符之间添加分隔符号,因为字符都是叶子节点,不会重复也不会互相包含(数据结构中有学过)。
##6.6 哈夫曼算法能够大幅提高压缩比率 ![哈夫曼效果](https://upload-images.jianshu.io/upload_images/17108100-41406d0319d5ed5a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ##6.7 可逆压缩与非可逆压缩 根据是否能还原为压缩前的状态,分为可逆压缩和非可逆压缩。 ![](https://upload-images.jianshu.io/upload_images/17108100-93150005ce6e3180.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 程序的exe文件和文本文件的每一个字符都不可丢失,所以要采用可逆压缩;对于图片来说,如果模糊一些也可以接受,则可以采用非可逆压缩。
#### 问题答案 ![答案](https://upload-images.jianshu.io/upload_images/17108100-545cd574f4e8fbff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#第7章 程序是在何种环境中运行的 ####本章问题: ![问题](https://upload-images.jianshu.io/upload_images/17108100-184816e872225bd9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##7.1 运行环境=操作系统+硬件 - 操作系统和硬件共同决定运行环境; - 在硬件中,CPU的种类是特别重要的参数,因为CPU只能解释其自身固有的机器语言,不同的CPU本身的机器语言也是不同的; - 机器语言的程序称为本地代码,程序员编写的代码称为源代码,市场上出售的一些软件,收录的是本地代码。 ##7.2 Windows克服了除CPU以外的硬件差异 - Windows本身需要为不同机型提供不同版本,如用于AT兼容机的Windows,用于PC-9081的Windows等; - Windows克服了除CPU外的硬件差异,这是因为应用程序可以通过Windows间接的向硬件发出指令,而不用直接控制硬件,所以只要Windows正常运行,同样的应用程序(本地代码)在不同的机型上也是可以正常运行的。 ![Windows在不同机型上使用同一应用](https://upload-images.jianshu.io/upload_images/17108100-700bd10b6a234b6e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/17108100-d777eeed53c1f335.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ##7.3 不同操作系统的API不同 - 应用程序向操作系统传递指令的途径称为API; - 不同操作系统的API有差异; - 将某一操作系统的应用程序移植到另一个操作系统上去,就要重写程序中应用到API的部分。
##7.4 FreeBSD Port帮你轻松使用源代码 - FreeBSD是Unix系列操作系统中的一种; - Ports 表示porting(移植)的意思,是FreeBSD操作系统中的一种机制; - 该机制会自动下载需要的源代码,然后编译器再生成适合当前环境运行的本地代码; - 通过Port机制,连CPU在内的硬件差异都可以克服了。 ![](https://upload-images.jianshu.io/upload_images/17108100-e068baff9a2f7611.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##7.5 利用虚拟机获得其它操作系统环境 这个不多讲了
##7.6 提供相同运行环境的Java虚拟机 - Java编译后并非生成本地代码,而是生成字节码,字节码运行的环境就是Java虚拟机; - Java虚拟机可以实现同样的字节码在不同环境下运行; - 不同Java虚拟机之间无法进行完整互换,想让所有字节码在所有Java虚拟机上任意运行是比较困难的(不太懂); - 当我们使用只适用于特定硬件的功能时,就会出现在其它Java虚拟机上无法运行,或者功能受限的情况; - 解释型语言速度较慢。
##7.7 BIOS和引导 - BIOS全称Basic Input/Output System; - BIOS储存在ROM中,是预先存储在计算机主机上的程序; - BIOS可以引导操作系统启动
####问题答案: ![答案](https://upload-images.jianshu.io/upload_images/17108100-c47d55eb3ca5a434.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
####[《程序是怎样跑起来的》(下)](https://www.cnblogs.com/xmusxy/p/10914346.html)