压缩数据
文件以字节为单位保存
- 从物理上对磁盘进行读写时是以扇区(512字节)为单位的,但是另一方面,程序则可以在逻辑上以字节为单位对文件的内容进行读写
- 在任何情况下,文件中的数据都是连续存储的
RLE算法机制
RLE算法:数据x数据重复次数
- 常被用于压缩传真的图像等
- 举例:AAAAAABBCDDEEEEEF,压缩后为A6B2C1D2E5F1
算法缺点
- 在实际的文本文件中,同样字符多次重复出现的清苦并不多见,不适合文本文件的压缩。
- 以1字符为单位的RLE,可能会出现压缩后更大的现象
哈夫曼编码提高压缩率
根据每个文本,统计字符出现频率,构造哈夫曼树。大概就是给出现频率最高的最短编码
压缩率很不错
可逆压缩和非可逆压缩
可逆压缩
- 我们把能还原到压缩前状态的压缩称为可逆压缩
- 程序的EXE文件就必须还原到压缩前的状态
非可逆压缩
- 无法还原到压缩前状态的压缩称为非可逆压缩
- 比如图像文件,多数情况下不要求还原到压缩前质量,有些模糊也可接受
其他
- Windows的标准图像数据形式为BMP,是完全未压缩的。BMP:Windows自带的画笔来做成的一种图像数据形式
- JEPG:数码相机等常用的一种图像数据形式
- TIFF:是一种通过在文件头中包含标签就能够显示出数据性质的图像数据形式
- GIF:这种格式要求色数不超过256色
压缩因为对于压缩比率、压缩时间和文件的要求的需求是不一样的,因此压缩算法有非常多种。
程序是在何种环境中运行的
单元前问题
- 应用的运行环境,指的是什么:
操作系统和计算机本身(硬件)的种类 - Macintosh用的操作系统(MacOS),在AT兼容机上能运行吗:
无法运行,不同的硬件种类需要不同的操作系统 - Windows上的应用,在MacOS上可以运行吗:
无法运行。应用是为了在特定的操作系统上运行而作成的 - FreeBSD提供的Ports,指的是什么
FreeBSD是一种Unix操作系统,通过在各个环境中编译Ports中公开的代码,就可以执行由此生成的本地代码了。
通过使用源代码来提供应用,并根据运行环境进行整合编译,从而得以在该环境下运行的机制 - Java虚拟机的功能是什么:
运行Java 应用的字节代码。只要分别为各个环境安装专用的Java虚拟机,同样的字节代码就能在各种环境下运行了
运行环境=操作系统+硬件
- 同一类型的硬件可以选择安装多种操作系统
- 机器语言的程序称为本地代码
- 源代码:程序员用C语言等编写的程序,在编写阶段仅仅是文本文件,文本文件在任何环境下都能显示和编辑。我们称之为源代码
- 通过对源代码进行编译,就可以得到本地代码。在市面上出手的windows的应用软件包,收录的就不是源代码,而是本地代码(EXE文件及DLL文件等形式)
能否从EXE文件破解源码?
Windows克服了CPU以外的硬件差异
windows无法吸收CPU类型的差异,市面上销售的windows应用软件,都是用特定的CPU的本地代码
Windows操作系统为什么能够识别不同的CPU所用的机器语言?
不同操作系统的API不同
- 操作系统的类型不同,应用程序向操作系统传递指令的途径也是不同的。
- 应用程序向操作系统传递指令的途径称为API(application programming interface),也称为系统调用
- API提供了任何应用程序都可以利用的函数组合,因为不同操作系统的API是有差异的,因此,在移植到其他操作系统时,就必须要重写应用中利用到API的部分。
FreeBSD Port帮你轻松使用源代码
既然CPU类型不同会导致同样的本地代码无法重复利用,那么为何不直接把源代码分发给程序?
- unix系列操作系统FreeBSD中,存在一种名为Port机制:能够结合当前运行的硬件环境来编译应用的源代码,进而得到可以运行的本地代码系统。如果目标应用的源代码没有在硬件上的话,Ports就会自动使用FTP连接到享关站点下载代码
移植
- 根据不同的运行环境来重新调整程序
利用虚拟机获得其他操作系统环境
即使不通过移植,也可以使用别的方法来运行其他操作系统的应用。
虚拟机软件
提供相同运行环境的Java虚拟机
除虚拟机之外提供不依赖于特定硬件及操作系统的程序运行环境的另一个办法
Java的含义:
- 一:作为编程语言的Java(Java也是将语言记述的源代码编译后运行。不过编译后生成的并不是特定CPU使用的本地代码,而是名为字节代码的程序)
- 二:作为程序运行环境的Java(字节代码运行的环境就称为Java虚拟机),会把字节代码变换成适合X86系列CPU使用的本地代码。虽然看上去迂回,但是因此能够实现同样的字节代码在不同的环境下运行
java虚拟机
- Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行
BIOS和引导
- Basic Input Output System基本输入输出系统。它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息。 其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。
- BIOS存储在ROM中,是预先内置在计算机主机内部的程序。
- BIOS除了键盘、磁盘、显卡等基本控制程序外,还有启动”引导程序“的功能。
- 引导程序是存储在启动驱动器起始区域的小程序。操作系统的启动器一般是硬盘,不过有时也是CD-ROM或软盘。
- 开机后,BIOS会确认硬件是否正常运行,没有问题的话就会启动引导程序。引导程序 的功能就是把在磁盘等记录的OS加载到内存中运行。虽然启动应用是OS的功能,但是OS并不能自己启动自己,而是引导程序来启动。
从源文件到可执行文件
单元前问题
- CPU可以解析和运行的程序形式称为什么代码
本地代码 - 将多个目标文件结合生成EXE文件的工具称为什么
链接器 - 扩展名为.obj的目标文件的内容,是源代码还是本地代码
本地代码 - 把多个目标文件收录在一起的文件称为什么
库文件 - 仅包含Windows的DLL文件中存储的函数信息的文件称为什么
导入库 - 在程序运行时,用动态申请分配的数据和对象的内存区域形式称为什么
堆
计算机只能运行本地代码
- 用某种编程语言编写的程序就称为源代码,保存源代码的文件称为源文件。C语言编写的源文件的扩展名通常是.c。源文件是简单的文本文件
- CPU能直接解析并运行的不是源代码而是本地代码的程序。
本地代码的内容
编译器负责转换源代码
- 编译器将高级编程语言编写的源代码转换为本地代码
- 编译器的三个要素:编程语言、CPU类型、操作系统
- 现在编译器默认集成到开发IDE中
仅靠编译时无法得到可执行文件的
- 编译后生成的不是EXE文件,而是.obj的目标文件,虽然目标文件的内容是本地代码,但是无法直接运行的,因为此时程序处于未完成状态
- 比如程序中,你写了一个average函数,同时你使用了函数库中的sprintf()和messagebox(),这两个函数源代码并没有记录函数的处理内容。因为,必须将存储这两个函数的目标文件同你的程序结合,否则处理就不完整,EXE文件也就无法完成
- 链接:将多个目标文件结合,生成一个EXE文件的处理
链接器:运行链接的程序
启动 及 库文件
一条链接例子
说明:
- 执行该命令后,程序所需的目标文件就会被全部链接生成sample1.exe
- sample1.obj是sample1.c编译后得到的目标文件。c0w32.obj这个目标文件记述的是同所有程序起始位置想结合的处理内容,称为程序的启动,由编译器提供。 import32.lib cw32.lib 是库文件,sprintf() 函数在 cw32.lib中,messagebox()在import32.lib中
- 即使程序不调用其他目标文件的函数,也必须要进行链接,并和启动结合起来。
- 库文件:把多个目标文件集成保存到一个文件中的形式
链接器指定库文件后,就会从中把需要的目标文件抽取出来,并同其他目标文件结合生成EXE文件。
使用库文件是为了简化链接器的参数指定多个目标文件这一过程
通过一目标文件的形式或集合多个目标文件的库文件形式来提供函数,就可以不用公开标准函数的源代码内容。
标准函数的源代码是编译器厂商的重要财产 - 标准函数:不是通过源代码的形式而是通过库文件的形式和编译器一起提供的
- 错误消息“无法解析的外部符号,”指无法找到记述目的变量及函数的目标文件,因为无法进行链接
DLL文件及导入库
- messagebox()提供显示消息框功能,是WINDOWS提供的API。Windows中,API的目标文件,并不是存储在通常的库文件中,而是存储在名为DLL文件的特殊库文件中。
- import32.lib中仅仅存储着两个信息,一时messagebox()在user32.dll这个DLL文件中,另一个是存储这DLL文件的文件夹信息,messagebox()的目标文件的实体实际上并不存在,我们把这种库叫做导入库。
- 静态链接库:存储着目标文件的实体,并直接和EXE文件结合的库文件的形式称为静态链接库。
可执行文件运行时的必要条件
- EXE文件是作为单独的文件存储在硬盘中的,通过资源管理器找到并双击EXE文件,就会把EXE文件的内容加载到内存中运行
- EXE文件中给变量及函数分配了虚拟的内存地址。在程序运行时,虚拟的内存地址会转换成实际的内存地址。链接器会在EXE文件的开头,追加转换内存地址所需要的必要信息。
这个信息被称为再配置信息。 - EXE文件的再配置信息,就成为了变量和函数的相对地址。
在链接后的EXE文件中,变量及函数就会编程一个连续排列的组。
EXE文件内容分为再配置信息、变量组和函数组
程序加载时会生成栈和堆
- EXE文件中并不存在栈及堆的组。栈和堆需要的内存空间是在EXE文件加载到内存后开始运行时得到分配的。
栈
- 用来存储函数内部临时使用的变量(局部变量),以及函数调用时所使用的参数的内存区域。
堆
- 用来存储程序运行时的任意数据及对象的内存领域
程序组成
- 内存中的程序,就是由用于变量的内存空间,用于函数的内存空间,用于栈的内存空间,用于堆的内存空间这4部分组成的。
栈、堆在内存使用方法上的区别
- 栈中对数据进行存储和舍弃(清理处理)的代码,是由编译器自动生成的,因此不需要程序员参与。使用栈的数据结构的内存空间,每当函数被调用时就会得到申请分配,并在函数处理完毕后自动释放。
- 使用堆的空间,需要程序员编写程序,来明确进行申请分配或释放
申请堆和释放堆
- C语言,malloc()函数进行申请分配,free()函数来释放
- C++语言,new申请分配,delete运算符来释放
内存泄漏
有点难度的Q&A
编译器和解释器
- 编译器是在运行前对所有源代码进行解释处理的。而解释器则是在运行时对源代码的内容一行一行地进行解释处理
分割编译
- 将整个程序分为多个源代码来编写,然后分别进行编译。最后链接生成一个EXE文件,这样每个源代码相对变短,便于程序管理。
Build
- 指的是连续执行编译和链接
叠加链接
- 将不会同时执行的函数,交替加载到同一个地址中运行。通过使用”叠加链接器“这一特殊的链接器即可实现。在计算机中分配的内存容量不多的MS-DOS时代,经常使用叠加链接。
垃圾回收机制
- 指对处理完毕后不再需要的堆内存的数据和对象进行清理,释放它们所使用的内存空间。c语言用的是free()函数,c++用的是delete运算符,java及c#,程序运行环境会自动进行垃圾回收。这样就可以避免由于程序员的疏忽而造成内存泄漏。
操作系统和应用的关系
单元前问题
- 在操作系统上运行的程序称为什么
应用或应用程序 - 调用操作系统功能称为什么
系统调用(system call)
操作系统功能的历史
历史
- 在没有操作系统的年代,人们研发出了监控程序,随着时代的发展,人们利用监控程序写程序的过程中,发现很多程序都有共通的部分。将基本的输入输出部分的程序加入监控程序中,初期的操作系统就诞生了,后面不断加入新功能,就不断发展成为现在的操作系统
- 操作系统本身并不是单独的程序,而是多个程序的集合体
要意识到操作系统的存在
系统调用和高级编程语言的移植性
c语言的time()函数,是用来取得当前日期和时间的函数
但windows操作系统提供返回当前日期和时刻的函数名,并不是time(),系统调用是在函数内部执行的
为什么要多此一举
- 因为人们希望不管是windows 还是Linux,都能够使用相同的源代码,因此,高级编程语言就使用独自的函数名,然后再在编译时将其转换成相应操作系统的系统调用
操作系统和高级编程语言使硬件抽象化
Windows操作系统的特征
32位64位操作系统
- 指处理数据的基本单位
通过API函数集来提供系统调用
提供采用GUI的用户界面
- GUI(Graphical User Interface,图形用户界面),即通过电机显示器中显示的窗口及图标等即可进行可视化操作的用户界面。
- 对于程序员来说,GUI不好开发,因为GUI中用户按照怎样的顺序操作是无法确定的
通过WYSIWYG实现打印输出
- What You See Is What You Get
- 同一个程序中就可以实现显示和打印这两方面的操作
提供多任务功能
- 采用时钟分割技术,即在短时间间隔内,多个程序切换运行的方式
提供网络功能及数据库功能
- Windows中,网络功能是被作为标准功能提供的。数据库(数据库服务器)功能有时也会在之后进行追加。网络功能和数据库功能,虽然并不是操作系统本身不可欠缺的功能,但是因为它们和操作系统很接近,所以被统称为中间件而不是应用。意思是处于操作系统和应用的中间。操作系统和中间件合在一起,也成为系统软件。应用不仅可以利用操作系统,也可以利用中间件功能。
- 相对于操作系统一旦安装就不能轻易替换,中间件则可以根据需要进行任意的替换。不过,大多数情况下,中间件变更后,应用也往往需要更换,因此中间件的变更也不是那么容易
通过即插即用实现设备驱动的自动设定
- 指新的设备连接后立刻就可以使用的机制
- 新的设备连接到计算机后,系统就会自动安装和设定用来控制该设备的设备驱动程序