内核开发和C++

cor*_*ump 25 c++ operating-system kernel

据我所知,即使普通操作系统有部分用其他语言编写,内核完全用C语言编写.

我想知道用C++编写内核是否可行,如果没有,那将是什么缺点.

Dev*_*lar 23

这在OSDev Wiki中有明确说明.

基本上,您必须为某些事物(如RTTI,异常)实现运行时支持,或者不使用它们(只留下要使用的C++子集).

除此之外,C++是更复杂的语言,所以你需要有一些更有能力的开发人员,而不是搞砸它.当然,Linus Torvalds讨厌C++纯属巧合.

  • 据我所知,在许多项目中实际上只使用了C++的一个子集.我的意思是,C++会在某种意义上说它可以像在C中一样编写,但是,在需要时,你可以使用一些封装,或者其他一些C语言难以获得的语言功能(我的意思是你可以得到一些)甚至在带有函数指针的C语言中的类. (3认同)
  • @coredump:通常使用C++子集的原因是许多业余爱好者开始自己开发内核,但是没有深入的理解来使完整的C++运行时支持可行.例如,异常处理是一个非常复杂的问题,并且从编译器实现者的角度来看,从效率的角度来看,它是"正确的".使用现有实现引发了软件许可的问题.此外,需要运行时支持的东西通常也涉及运行时*成本*,如果没有,你真的不想要它. (3认同)

mar*_*rko 23

有很多用C++实现的常用操作系统(或部分)的例子 - IOKit - MacOSX和IOS的设备驱动子系统是用EC++实现的.然后是eCOS RTOS - 内核用C++实现,甚至使用模板.

操作系统传统上充斥着以C语言实现的OO概念的示例.在Linux设备模型kobject中实际上是驱动程序和设备对象的基类,完整的DIY v-table和一些在宏中实现的时髦安排.下铸造.

Windows NT内核具有更深入的内核对象继承层次结构.对于抱怨内核代码中异常处理的适用性的所有neigh-sayers,确实提供了这样的机制.

传统上,反对在内核代码中使用C++的论点是:

  • 可移植性:适用于所有预期目标平台的C++编译器的可用性.这不再是一个问题
  • C++语言机制的成本,例如RTTI和异常.显然,如果要使用它们,标准实现是不合适的,并且需要使用特定于内核的变体.这通常是使用EC++的驱动因素
  • C++ API的稳健性,特别是脆弱的基类问题

毫无疑问,使用异常和RAII范例将极大地提高内核代码质量 - 您只需要查看BSD或Linux的源代码以查看替代方案 - 使用gotos 实现的大量错误处理代码.


Sev*_*ive 10

为解决Torvalds的问题和其他地方提到的其他问题:在用C++编写的硬RT系统中,不使用STL/RTTI /异常,并且相同的主体可以应用于更宽松的Linux内核.关于"OOP内存模型"或"多态性开销"的其他问题基本上表明程序员从未真正检查在程序集级别或内存结构中发生的事情.C++是高效的,并且由于优化的编译器比C程序员编写查找表的效率高很多倍,因为他没有手头的虚函数.

在普通程序员手中,C++不会添加任何额外的汇编代码与C编写的代码.在阅读了大多数C++构造和机制的asm翻译之后,我会说编译器甚至有更多的空间来优化vs C,并且有时可以创建更精简的代码.因此,就性能而言,使用C++和C一样高效,同时仍然在C++中利用OOP的强大功能.

所以答案是它与事实无关,基本上围绕偏见而不是真正知道CPP创建的代码.我个人喜欢C几乎和C++一样多,我不介意,但是没有理由反对在Linux之上分层面向对象的设计,或者在内核本身,它会很好地完成Linux.

  • @TechZila我读了asm,但你没必要,Scott Meyers为这些科目的CPP新手提供新手友好帮助.1)泄漏在C中更常见,因为多态性(困扰内核代码)是用查找表完成的,并且指针地狱全部都是C开源,直到它成熟为止.2)C++永远不会添加额外的功能,您必须明确指定它们.3)许多军用Hard RT系统使用C++,事实上我在海法创建Iron Dome的地方讲授了RT C++.许多医疗Hard RT都是一样的. (7认同)
  • @TechZilla:我用C和C++编写过很多项目.每次我必须恢复到C中的手动内存管理,返回代码检查和清理程序时,我都会畏缩**.如果C++没有提供任何东西,只有构造函数,析构函数和`<vector>`,我会采取它.我在过去的15年中所做的大部分工作都是在C++中重新实现*C代码(或者由C/Java编码器编写的非常差的C++代码,而不是理解差异)来实现它*更多*可维护.我责怪教师,在线教程和"试错"心态,而不是语言. (5认同)
  • @TechZilla听起来像一些热心的,公共的强化,"不信任苏格兰人"拖钓.我使用了Rust,SPARK,C++和C裸机,它们有自己的优点和缺点.使用强制约定的C++的严格子集(考虑支持RTTI,模板,异常,标准,分配器等的成本/风险)绝对可行且具有更好的namspacing. (4认同)
  • 4)专业知识?不要使用STL容器,不需要时不要写“虚拟”(影响较小),不要使用RTTI。完毕。5) 如果使用函子,在传递函数指针的常见情况下,您可以超过 C 的性能,因为函子在传递时可以内联。6)游戏的要求比Linux内核更严格,不要屈尊他们,并且我之前评论中第3项提到的系统可靠性要求更高。7) 抱歉,当 Linus 做出 CPP 与 C 的决定时,他的 C++ 知识比这个网站上的大多数专家要少。 (3认同)
  • 因此效率是平等且更好的(Meyers的书可以为您提供帮助),知识要求也很低(请参阅我的上一条评论中的第4和第5条)可靠性(项目1),仅由于C强迫您使用查找表而无法比拟。内核普遍存在的多态性的指针,但这只是在C中模仿C ++的一个示例,其他则是无法读取的宏。我们在这里只是表面。看,我在14年前在Hard RT C中切换到C ++后14年前仍然抱有同样的怀疑,现在我仅在上传到C开源时才使用C。不要信教,请读Scott Meyers,他是一个很好的入门者 (2认同)

Roo*_*ook 8

您可以用或多或少的语言编写OS内核.

但是,有几个理由喜欢C.

  • 这是一门简单的语言!这里的魔法很少.您可以在没有太多困难的情况下推断编译器将从源代码生成的机器代码.
  • 它往往很快.
  • 没有太多必需的运行时; 将其移植到新系统所需的工作量很小.
  • 有许多可靠的编译器可用于许多不同的CPU和系统架构.

相比之下,C++可能是一种非常复杂的语言,它涉及到将大量日常高级OOP代码转换为机器代码所需的大量魔力.关于生成的机器代码更难以推理,当你需要开始调试恐慌的内核或片状设备驱动程序时,你的OOP抽象的复杂性将开始变得非常恼人......特别是如果你必须通过用户不友好的方式来做将端口调试到目标系统中.

顺便说一句,Linus并不是唯一对系统编程语言有强烈意见的操作系统开发人员; OpenBSD的Theo de Raadt也就这个问题做了一些选择.

  • 相反,在基于C的内核中,我们看到了OO概念的DIY实现 - 相当多的轮子重新发明,人们可以免费使用C++.这是一个非常真实的代码质量问题,因为它会导致更复杂,特别是在不太可能接收正确测试的错误路径中. (9认同)
  • C并不简单.它有一个非常复杂,丑陋且容易出错的声明语法(在声明指针指针时,错误地使用`const`或`volatile`).它的类型系统和促销是每个新手的另一个痛苦(有时也是专业人士).它有许多未定义的,未指定的和特定于实现的行为,但是,更具魔力(=惊喜)!浮点虽然在内核中没有大量使用,但是另一个有问题的领域.相比之下,汇编语言更直接,更简单,更不令人惊讶. (7认同)
  • @Marko:事实上,很多开发人员很难在没有他们熟悉的抽象层的情况下应对,而且由此产生的黑客通常很糟糕,因为他们不是语言开发人员.抽象在更高级别的应用程序中很有价值,但在靠近金属编码时则不然.一个没有纪律的编码人员可以用任何语言写垃圾; 这不是语言的错,它让他们这样做. (2认同)