据我所知,即使常见的操作系统有部分是用其他语言编写的,内核完全是用 C 编写的。
我想知道用 C++ 编写内核是否可行,如果不可行,会有什么缺点。
据我所知,即使常见的操作系统有部分是用其他语言编写的,内核完全是用 C 编写的。
我想知道用 C++ 编写内核是否可行,如果不可行,会有什么缺点。
这在OSDev Wiki中有明确的介绍。
基本上,您要么必须为某些事物(如 RTTI、异常)实现运行时支持,要么避免使用它们(只留下 C++ 的一个子集)。
除此之外,C++ 是更复杂的语言,因此您需要有一些更胜任的开发人员,他们不会把它搞砸。当然,Linus Torvalds 讨厌 C++ 纯属巧合。
有很多用 C++ 实现的常用操作系统(或其中的一部分)的例子——IOKit——MacOSX 和 IOS 的设备驱动子系统是用EC++实现的。然后是eCOS RTOS——内核是用 C++ 实现的,甚至使用模板。
操作系统传统上充斥着用 C 语言实现的 OO 概念示例。在 linux 设备模型kobject
中,实际上是驱动程序和设备对象的基类,完成了 DIY v-tables 和一些在宏中实现的时髦安排,用于 up 和向下铸造。
Windows NT 内核有一个更根深蒂固的内核对象继承层次结构。对于所有抱怨内核代码中异常处理的适用性的邻居来说,正是提供了这样一种机制。
传统上,反对在内核代码中使用 C++ 的论点是:
毫无疑问,异常和RAII范式的使用将极大地提高内核代码质量——你只需要查看 BSD 或 linux 的源代码就可以看到替代方案——使用 s 实现的大量错误处理代码goto
。
为了解决 Torvalds 的问题以及此处其他地方提到的其他问题:在用 C++ 编写的硬 RT 系统中,不使用 STL/RTTI/异常,并且可以将相同的原则应用于更宽松的 Linux 内核。关于“OOP 内存模型”或“多态性开销”的其他担忧基本上表明程序员从未真正检查过汇编级别或内存结构发生的情况。C++ 和 C++ 一样高效,并且由于优化的编译器比 C 程序员编写查找表的效率要高很多倍,因为他手头没有虚函数。
在普通程序员的手中,C++ 不会添加任何额外的汇编代码而不是 C 编写的代码。在阅读了大多数 C++ 结构和机制的 asm 翻译后,我想说编译器甚至比 C 有更多的优化空间,并且有时可以创建更精简的代码。因此,就性能而言,使用 C++ 和使用 C 一样高效非常容易,同时仍然利用 C++ 中 OOP 的强大功能。
所以答案是它与事实无关,基本上围绕着偏见,不知道 CPP 创建了什么代码。我个人喜欢 C 几乎和 C++ 一样多,我不介意,但是没有理由反对在 Linux 之上或在内核本身中分层面向对象的设计,它会给 Linux 带来很多好处。
您可以或多或少地用您喜欢的任何语言编写操作系统内核。
然而,有几个理由更喜欢 C。
相比之下,C++ 可能是一种非常复杂的语言,它需要做很多魔法来将越来越高级的 OOP 代码转换为机器代码。对生成的机器代码进行推理变得更加困难,当您需要开始调试恐慌的内核或不稳定的设备驱动程序时,您的 OOP 抽象的复杂性将开始变得非常烦人……尤其是如果您必须通过用户不友好的方式进行调试调试端口到目标系统。
顺便说一句,Linus 并不是唯一对系统编程语言有强烈看法的操作系统开发人员。OpenBSD 的 Theo de Raadt 也对这个问题做了一些选择引用。
虽然 (ANSI) C 有一些“诚实”的东西,但 C++ 也有一些“诚实”的东西,以不同的方式。
C++ 对抽象对象的句法支持是非常值得的,无论是什么应用程序空间。可用于减轻误称的工具越多,效果就越好……而类就是这样的工具。
如果现有 C++ 编译器的某些部分不能很好地适应内核级的现实,那么削减一个以“正确”方式执行它的编译器的修改版本,并使用它。
就程序员的能力和代码质量而言,可以用 C 或 C++ 编写丑陋或崇高的代码。我认为通过在内核级别禁止它来歧视那些实际上可以很好地编写 OOP 的人是不正确的。
也就是说,即使作为一名经验丰富的程序员,我也怀念过去用汇编程序编写代码的日子。我喜欢它们……C++ 和 ASM……只要我可以使用 Emacs 和源代码级调试器 (:-)。
多年后的修订:
回顾过去,我想说最大的问题实际上是 C++ 中的大量高级特性,这些特性要么隐藏,要么不受程序员的控制。该标准不强制执行任何特定的实现方式,即使大多数实现遵循共同的理智,也有很多充分的理由要 100% 明确并完全控制事物在 OS 内核中的实现方式。
这允许(只要您知道自己在做什么)减少内存占用,基于访问模式而不是 OOP 范例优化数据布局,从而提高缓存友好性和性能,并避免可能隐藏在大量数据中的潜在错误C++ 的高级特性。
请注意,即使更简单,甚至 C 在某些情况下也太难以预测,这也是内核代码中还有很多特定于平台的程序集的原因之一。
C 的一大好处是它的可读性。如果您有很多代码,则更具可读性:
foo.do_something();
或者:
my_class_do_something(&foo);
每次使用 foo 时,C 版本都会明确说明 foo 是哪种类型。在 C++ 中,你有很多很多模棱两可的“魔法”在幕后进行。所以如果你只看一小段代码,可读性会差很多。