您提到了代码如何特定于CPU,为什么也必须特定于OS。实际上,这是这里许多答案都假定的一个有趣的问题。
CPU安全模型
在大多数CPU架构上运行的第一个程序在称为内部环或环0的内部运行。特定的CPU架构实现环的方式各不相同,但事实是,几乎每个现代CPU至少都有两种操作模式,一种是特权模式,并运行“裸机”代码,该代码可以执行CPU可以执行的任何合法操作,而另一种是不受信任,并运行只能执行定义的安全功能集的受保护代码。但是,某些CPU的粒度要高得多,为了安全地使用VM,至少需要1或2个额外的环(通常用负数标记),但这超出了此答案的范围。
操作系统进来的地方
早期的单任务操作系统
在早期的DOS和其他早期的基于单任务的系统中,所有代码都在内部环中运行,您运行的每个程序都具有整个计算机的全部功能,如果行为不当,包括擦除所有数据甚至造成硬件损坏,实际上可以执行任何操作。在一些极端的情况下,例如在非常老的显示屏上设置无效的显示模式,更糟糕的是,这可能是由简单的错误代码引起的,没有任何恶意。
实际上,此代码在很大程度上与操作系统无关,只要您具有能够将程序加载到内存中的加载程序(对于早期的二进制格式来说就非常简单),并且该代码不依赖任何驱动程序,而是实现了所有硬件访问本身就应该在以下条件下运行只要在环0上运行,任何操作系统都可以。请注意,如果这样的简单操作系统仅用于运行其他程序,并且不提供其他功能,则通常称为监视器。
现代多任务操作系统
包括UNIX在内的更现代的操作系统,以NT开头的Windows版本以及其他现在不为人所知的OS决定在这种情况下进行改进,用户需要诸如多任务处理之类的附加功能,以便可以一次运行多个应用程序并提供保护,因此存在一个错误(或恶意代码)在应用程序中将不再对计算机和数据造成无限的破坏。
这是使用上述环完成的,操作系统将只在环0中运行,而应用程序将在外部不受信任的环中运行,只能执行操作系统允许的一组受限操作。
但是,增加的实用性和保护需要付出一定的代价,程序现在必须与OS配合使用才能执行不允许自己执行的任务,例如,它们无法再通过访问其内存并随意更改来直接控制硬盘。数据,相反,他们必须要求OS为它们执行这些任务,以便它可以检查是否允许他们执行该操作,而不更改不属于它们的文件,还可以检查该操作确实有效,并且不会使硬件处于未定义状态。
每个OS都针对这些保护方案决定了不同的实现方式,部分基于该OS所设计的体系结构,部分基于所讨论的OS的设计和原理,例如UNIX将重点放在适合多用户使用的计算机上, Windows被设计为更简单,可在单个用户的较慢硬件上运行的情况下可用的功能。在X86上,用户空间程序与OS进行通讯的方式与在ARM或MIPS上进行通讯的方式完全不同,例如,迫使多平台OS围绕在目标硬件上工作的需要做出决策。
这些特定于OS的交互通常称为“系统调用”,涵盖了用户空间程序如何通过OS完全与硬件交互,它们在根本上因OS的功能而异,因此通过系统调用完成其工作的程序需要特定于操作系统。
程序加载器
除了系统调用外,每个OS还提供了不同的方法来从辅助存储介质加载程序并将其加载到内存中,为了可由特定的OS加载,该程序必须包含一个特殊的标头,向OS描述如何加载并运行。
这个头文件曾经很简单,以至于用不同格式编写一个加载器几乎是微不足道的,但是对于像elf这样的现代格式,它支持动态链接和弱声明等高级功能,现在操作系统几乎不可能尝试加载二进制文件这不是为它设计的,这意味着,即使没有系统调用不兼容性,也很难以一种可以运行程序的方式将程序放在ram中。
图书馆
程序很少直接使用系统调用,但是,通过将系统调用以一种稍微友好的格式包装用于编程语言的库,它们几乎可以独占地获得其功能,例如,C在Linux下具有C标准库和glibc,在Linux下具有类似的库和win32库在Windows NT及更高版本中,大多数其他编程语言也具有类似的库,它们以适当的方式包装系统功能。
这些库甚至可以在某种程度上克服如上所述的跨平台问题,有一系列库的设计目的是为应用程序提供统一的平台,同时在内部管理对各种操作系统(例如SDL)的调用,这意味着程序不能与二进制兼容,使用这些库的程序在平台之间可能具有共同的来源,从而使移植与重新编译一样简单。
例外情况
尽管我在这里已经说了很多,但仍在尝试克服无法在多个操作系统上运行程序的局限性。Wine项目就是一个很好的例子,该项目成功地模拟了win32程序加载器,二进制格式和系统库,使Windows程序可以在各种UNIX上运行。还有一个兼容层,允许多个BSD UNIX操作系统运行Linux软件,当然,苹果自己的填充程序也允许一个人在MacOS X下运行旧的MacOS软件。
但是,这些项目需要大量的手动开发工作。根据这两个OS的不同程度,难度从很小的填充到对另一个OS的接近完全仿真的范围,这通常比编写整个操作系统本身要复杂得多,因此这是例外,而不是常规。