程序是如何跑起来的
- 前言
- 磁盘与内存的关系
- 虚拟内存
- dll 文件
- 运行环境
- 从源文件到可执行文件
前言
不得不说,在这个假期借助“微信阅读”读到了很多有意义的书。不仅是思想境界上的,还有专业方向的。这一次我是在周三还是周四的一个活动中淘到了这本书,一开始大致看了一下,还只以为是的认为自己都大致了解了(毕竟也是学了好几年了嘛,得有点自信。)。在看了之后是真的赞叹,书是不嫌多的,总是很吸取到对自己有帮助的地方。
这是一篇读书笔记性质的博客,有自己的理解,同时对于书中的内容也是进行选取的(重点选择自己觉得之前没有了解或没有掌握到的知识)。
这本书呢,正如其名,大体是介绍了程序是如何在计算机中运行的。首先呢,对于没有学过太多有关方面知识(如计组、计网和编译原理等)也是可以通过这本书了解到一个大体框架的(比如这其中涉及到了很多方面的知识,那么在学到相关方面的课程的时候我们就大致明白了这个课程与其余知识的联系,能让我们能更好地对知识进行融会贯通);如果是学到了相关方面的知识,那么我认为较大的好处是一方面可以对我们所学的知识有一个新的认知与巩固(了解到在真实情况下所学的知识是如何使用到的),另一方面则是能查漏补缺将知识体系补充完整。
磁盘与内存的关系
在现如今的计算机体系中,程序必须要读到内存中才是可以正常运行的。而这就使得磁盘和内存之间就存在着很多巧妙的设计。
虚拟内存
虚拟内存指的是将磁盘的一部分作为假象的内存来使用。
通过借助虚拟内存,在内存不足的时候也可以运行程序。
由于CPU只能执行内存中的程序。虚拟内存虽然说是将一部分磁盘当作内存来使用,但实际运行部分的程序是必须在内存中的。那么我们可以想到,我们会将程序分成很多部分使得内存能一次性容纳在运行的部分。 在很多地方,将磁盘上虚拟内存的内容转移到实际内存中的操作称之为 ----- 置换。
现如今,虚拟内存主流的方式分为两种:分页式和分段式。在Windows中采用的是分页式的手段。该方式指的是在不影响程序构造的基础上,将程序按照一定大小的页进行分割,并以页为单位在内存和磁盘间进行置换。 如下图
为了实现虚拟内存的功能,Windows在磁盘上提供了虚拟内存使用的文件(页文件)。该文件由Windows自动做成和管理。文件大小也就是虚拟内存的大小。我们可以通过Windows的控制面板查看或变更当前虚拟内存的设定。如下图
dll 文件
DLL(dynamic link library)文件,是在程序运行的时候可以动态加载library(函数和数据的集合)的文件。
多个应用可以共有一个DLL文件。而通过共有同一个DLL文件可以达到节约内存的效果
Windows的操作系统本身也是一个DLL文件的集合体。除了利用多个DLL文件可以节约内存之外,使用DLL文件可以在不变更EXE文件的情况下,只通过升级DLL文件就可以更新了。
运行环境
在程序中是离不开所依赖的运行环境的。因此,出现了我们如今常见的虚拟环境和docker等手段来构建适合程序运行的环境。那么程序的运行环境是什么呢?其实大致可以这么说:运行环境 = 操作系统 + 硬件。也就是说,操作系统和硬件决定了程序的运行环境。
首先呢,现如今的同一类型硬件是可以选择安装多种操作系统的。同时,CPU只能解释其自身固有的机器语言。也就是说不同的CPU能解释的机器语言的种类也是不同的。我们都知道程序最终都是要编译成为机器语言的,这样才能被CPU所执行。因此可以这么说,运行环境是为了使得程序最终编译成的机器语言符合该计算机的CPU能执行的形式的这个目标。(如下图)
同时,现如今的体系结构大部分是,程序操控硬件是通过操作系统来间接控制的。也就是说如果操作系统不同,应用程序向操作系统传递指令的途径也会有所不同。也就是说,在同类型的操作系统下,不管硬件如何,API基本上是没有差别的。(这也是使用操作系统的一个好处,对上层进行了透明操作)。因而,针对某特定操作系统的API所编写的程序,在任何硬件都可以运行。当然,可以由于CPU种类的不同,在本地上边的代码(机器语言)是有所不同的。
- 那么我如果想在Windows上运行Linux的程序的话什么办?一个方法就是利用虚拟机获得其他操作系统环境。也就是说我们在Windows上配置好Linux的虚拟机,之后程序就能调用Linux上的API从而能运行了,同时该Linux虚拟机需要适配好该Windows的硬件配置。(因为这个Linux调用的是Windows上的硬件)。(这个技术目前大部分是使用docker来替代了)
- 还有一种方式是使用想Java虚拟机这样的方式。我们的源代码会统一先编译为名为字节代码的程序。字节代码的运行环境就称为Java虚拟机。Java虚拟机是一边把Java字节代码逐一转换成本地代码一边运行的。(最终还是要转换成本地CPU能执行的本地代码,不同的是这个任何交给了Java虚拟机来进行转换----这也是Java运行较慢的主要原因)
从源文件到可执行文件
- 将多个目标文件(通过对源文件进行编译才得到目标文件)结合生成EXE的工具称为链接器。通过编译和链接之后才能得到EXE文件。
- 把多个目标文件收录在一起的文件称为:库文件
- 仅包含Windows的DLL文件中存储的函数信息的文件称为:导入库。将导入库信息结合到EXE文件中,这样程序在运行时就可以利用DLL内的函数了。
- 链接器会从库文件中抽取除必要的目标文件并将其结合到EXE文件之中。此外,还存在一种程序运行时结合的DLL形式的库文件。
Windows中的编译及链接机制如下图