将程序分解n > 1
成碎片的另一种方法是将其保持在n == 1
碎片中。为什么这很糟糕?好吧,它并不总是很糟糕(也许 BIOS 就是一个很好的例子?)。但是对于用户程序来说通常是这样。为什么?首先我们需要定义什么是程序。
什么是程序?
一个简单的“程序”,粗略地说,由入口点(即主函数的偏移量)、函数和全局变量组成。函数由有关运行该函数所需的局部变量的指令和信息组成。要执行的程序必须加载到主存储器/RAM 中(上述信息)。因为我们的程序有函数(而不仅仅是跳转语句),这意味着堆栈的存在,这意味着存在管理堆栈的包含环境。(我想你可以有一个管理自己的堆栈的程序,但我认为你的程序不再是一个程序,而是一个环境。)这个环境包含程序,从入口点开始并执行每条指令,无论是“转到 RAM 的这一部分并将其添加到此寄存器中的任何内容中” 或“如果此寄存器全为 0,则向前跳转这么多指令并在那里继续执行”,或直到程序将控制权交还给其环境。(这有点简化了——多进程环境中的上下文切换、非法内存访问、非法指令等也可能导致控制从程序中被夺走。)
无论如何,我们有两个选择:一次加载整个程序,或者将其存储并分段加载。
n == 1
一次完成所有操作有一些好处:
n > 1
但是,有一些缺点反映了优点:
大多数程序大部分时间不会执行所有代码路径。我认为有一些研究表明,在大多数程序中,大部分执行时间都花在了程序中存在的一小部分指令上。换句话说,大约 20% 的程序在 80% 的时间内被执行(我刚刚提出了这个特定的数字——但你明白了)。如果我们将程序划分得足够多,并且只加载需要的指令集(即函数),那么我们就不会浪费时间加载 80% 我们永远不会使用程序的执行。沿着这些思路,如果我们最终只加载我们需要的程序的一部分,我们最终可以一次在我们的 RAM 中容纳更多并发执行的程序。
大多数程序共享相似的功能(即存储数据/树/哈希/排序/等,读取输入,写入输出等),如果每个程序都有自己的本地副本,那么您就不能重用指令代码。
许多程序依赖于其他程序的存在,并由不同的公司/团体/个人维护。通过发布版本化模块,我们不必一直同步发布。
结论
这些不是唯一要考虑的问题,而是我想到的第一个问题。我建议阅读有关编译器、链接器和操作系统的信息。这将比我更彻底地回答这个问题,而且我确信这已经提出了其他问题。回顾一下 dll 并不是在所有情况和情况下打包可执行程序的“最佳”方式——它们有特定的用途和优点和缺点。