Languages

来自osdev
跳到导航 跳到搜索

许多编程语言,其中有些语言比其他语言更适合操作系统开发和内核编写。 本页将对此进行深入讨论。

历史

早期的操作系统完全是用各自CPU的汇编方言编写的,对于当前愿意投入时间和精力使用这些方言的开发人员来说,这仍然是一个选择。 即使操作系统主要是用高级语言编写的,仍然有一些部分只能在汇编中完成。 甚至一部分很特殊的操作系统开发人员专门选择在汇编中工作,还有一些直接在机器语言中工作(尽管这在今天是罕见的)。

过去,许多高级语言被用于操作系统开发,包括C、Forth、Lisp、 C#C++、Modula-2、Ada、Bliss、Smalltalk和PL/1。 然而,并不是所有的语言都适合OS开发,并且在除C之外的许多语言中,为了提供支持语言的建模抽象能力需要提供适当的运行时环境,这又会需要进行相当数量的汇编语言开发。 无论是在操作系统开发还是嵌入式系统中,诸如C、Modula-2、Ada、Bliss、PL/M和XPL之类的语言都是专门为底层系统编程而设计的。而诸如Forth之类的语言都包含了必要的底层功能,即使它们不专门用于此目的。

警告

不是所有的语言都适合于低级系统编程[待列出?],它们要么没有合适的低级开发工具可用,要么需要特定的运行时支持,而C不会遇到这样的问题。 此外,绝大多数与操作系统相关的资源(如教程和操作示例,包括本wiki)都假定C是主要的开发语言,因此操作系统开发人员至少应该能够阅读C代码。

使用C以外的语言需要付出大量的额外努力。 但也有一些开发者愿意投入这一努力,以使操作系统的开发符合他们的思维方式(例如:programming paradigms)。

另一方面,试图用解释语言或字节码语言(如Perl或Java)编写操作系统具有极大的挑战性,因此不太可能成功。 当然,有一些关于它的研究项目,但迄今为止,还没有任何东西完全改变我们编写内核的方式。 如果要尝试用HTML编写操作系统……我觉得你还是先再学习一段时间再来弄吧。

所以,忠告已经传达了。现在你应该做出选择,希望是明智的选择。

我可以使用XYZ语言吗?

如果你想知道你最喜欢的语言是否适合开发操作系统,请考虑最重要的原则—— 应该有一种用你的语言做底层工作的方法。

同样,在开始之前得回答以下问题:

  • 你能否处理具有特定位和字节排列的数据结构(例如,MMU结构和类似的东西是必需的)?或者你有相应的工具吗?
  • 你能控制内存分配/释放吗? 或者,你是否可以至少将大块内存细分为其他函数可以透明使用的较小块(对于任何类型的内存管理都是必要的)? 这里的重要后果是-你是否能以自己的语言获得个人内存管理器的某种支持?
  • 你是否能够构建一个自给自足的运行时库(run-time library )来支持所需的语言功能?
  • 你能否轻松地将XYZ与一些汇编代码连接起来(是的,你将拥有一些汇编代码,至少在你编写底层运行时库(run-time library)时必须是这样的)?
  • 如果XYZ适合其他点,并且是一种解释语言,那么你能否使用XYZ调用来自原始字节的代码,即向特定地址跳转并继续执行(这对于加载和运行程序是必需的)?

如果这些问题中的任何一个被证明是'哦不,我不能用语言XYZ做到这一点',那么XYZ很可能无助于操作系统开发。 这些特殊问题通常都需要通过修改语言和编写新的编译器才能解决。

我能不能为XYZ编写编译器?

编译器是软件中少数几个与操作系统具有相似复杂性的东西之一。 既然你已经在计划写一个操作系统,那么决定做一个编译器就好像是去找锻造金属的新方法来制造一辆更好的汽车。 尽管如此,还是有一些操作系统开发者认为自己能够迎接挑战。 经典的教程是"龙书"(参考书籍页上的编译器-原理、技术和工具)。

然而,这并不意味着你可以忽略C和汇编; 事实上,对编译的代码生成阶段来说,理解汇编比对操作系统开发更重要(除非你完全避开高级语言), 对于编译器设计人员来说,扎实掌握目标语言(译者注:这里指汇编语言)是必须的。 另外,正如已经说过的,关于操作系统开发的大部分信息都是面向C开发人员的,除非你打算完全独立工作,否则至少必须具备阅读C的扎实能力。

同时,再考虑一下:你的编译器会用什么语言编写?汇编语言当然不是首先,所以你又得选择C语言,或者还是你最喜欢的语言XYZ。 如果你使用后者,你将如何引导自己?如果使用前者,则需要移植libc和GCC——到现在你还“确定”希望开发自托管的语言吗?

但我听说过一个用XYZ语言编写的操作系统,它不是解释语言吗?

这是一个骗局。 没有所谓的'解释语言'。 任何语言都可以使用解释器或编译器来实现;即使在一个操作系统项目中,也有一些形式的'解释'可以应用于系统操作。

你可能会不时听到用某些语言编写的操作系统,这些语言通常是解释执行的,或者使用了某种解释器的:JavaOS, Genera (the Symbolics Lisp Machine OS), Pilot-OS (Xerox Star 工作站的系统,主要用Mesa语言编写),UCSD Pascal,各种Forth系统等。 其中大部分可分为三类:

  • 操作系统运行在用汇编语言或某些系统语言(如C)编写的低级解释器中,这实际上才是与硬件交互的语言。 实际上,这些语言实现的所谓'操作系统'只是在另一个底层操作系统上运行的应用程序。 Pilot OS、UCSD Pascal和一些Java操作系统都是这样工作的,不过它们也有一些编译成本机代码的模块(见下文)。
  • 全部或部分代码已编译为本机代码。 这可能涉及使用具有减少的运行时要求的语言的子集(例如,Pre-Scheme, 或者 Slang - 虽然到目前为止,它们还没有用于操作系统开发,但它们确实演示了这种低级别的实现语言,可以这样使用)。
    • Forth-基于Forth的操作系统是这种情况的特例。 尽管通常被描述为一种解释性语言, 其中许多FORTH系统使用的threaded-code interpreters工作方式,与大多数其他解释器不同;实际上,解释器将遍历代码所包含的各种Forth 'Words',解析到在汇编或编译代码的实现,然后再实际执行。 此外,Forth系统包含一种特殊类型的汇编程序,它生成专门供解释器使用的代码;此外,常用的'Word'会根据需要编译成本机代码。 最后,许多嵌入式系统是使用专用硬件(见下文)来支持该语言。
    • 大多数Lisp系统可以自由地混合解释和编译代码,自20世纪70年代末以来,在几乎所有'严肃'的Lisp系统中,Listener REPL(Lisp系统的'命令行')已不再是一个解释器,而是一个编译系统——每一段代码至少都是动态编译的。 虽然没有任何重要的Lisp操作系统是在不使用特定语言的硬件支持(见下文)的情况下开发的,但如果有,它肯定不是一个纯粹的解释系统。
  • 这类非通常概念上的解释系统运行在专门的硬件和微操作码(microcode)上,这些硬件和操作码充当其主要语言的固化'解释器',或它通常使用的可移植字节码。 这种类型的系统包括SOAR(RISC上的Smalltalk)、Recursiv系统、Lillith Modula-2系统和Burroughs 6500(60年代设计用于运行Algol-60的大型机)。 这些系统的编程技术无法在常规硬件上工作。 例如:
    • CADR Lisp机器体系结构 有大量的指令集,由硬件支持某些高级操作,如type-tag checking和GC。 它有一个tagged architecture意味着36位寻址字的一部分被指定用于类型信息。 通常,这些机器有多种编译器,包括一个用于系统语言Lisp的编译器,该编译器能够利用额外的指令集。
    • Rekursiv Single-Board Computer硬件支持可创作指令集(即,你可以动态添加微操作码指令)和关联内存调度表,以支持面向对象编程。