为什么驱动开发要使用C语言而不是C#?

5

可能是 https://dev59.com/RnVD5IYBdhLWcg3wI3-L 的重复问题。 - schot
@schot 我认为这是一个相关的问题,但不是重复的。 - Earlz
@Earlz:你可能是对的。另一个相关的问题:https://dev59.com/snNA5IYBdhLWcg3wWseK - schot
7个回答

15
因为C#程序无法在内核模式(Ring 0)运行。

6
+1,但要补充一点:Windows现在也支持用户模式驱动程序,但仅限于有限的范围。http://www.microsoft.com/whdc/driver/wdf/UMDF.mspx - Brian Rasmussen
@Brian,是的,那是一个很好的评论。 - Darin Dimitrov
2
然而,已经有研究项目在像C#这样的托管语言中开发操作系统。请参见http://en.wikipedia.org/wiki/Singularity_%28operating_system%29。 - Brian

6
主要原因是C语言比C#更适合于低级(接近硬件)开发。C语言被设计为一种可移植的汇编代码形式。此外,在某些情况下,使用C#可能会很困难或不安全。关键时刻是当驱动程序在ring-0或内核模式下运行时。大多数应用程序都不适合在此模式下运行,包括.NET运行时。

尽管从理论上讲可能可以做到,但在许多情况下,C语言更适合于该任务。一些原因是更严格地控制生成的机器代码以及在直接与硬件交互时更接近处理器通常更好。


3
忽略C#的受限制的管理语言一会儿,面向对象的语言(如C#)通常在底层执行操作,这可能会干扰驱动程序开发。驱动程序开发——实际上是读取和操作硬件中的位——通常具有紧密的时间限制,并使用其他类型编程中避免的编程实践,例如繁忙等待和解引用从整数常量值设置的指针。设备驱动程序通常实际上是用C和内联汇编混合编写的(或利用某种其他发出C编译器不通常生成的指令的方法)。仅低级锁定机制(用汇编编写)就足以使使用C#变得困难。C#具有许多锁定功能,但当您深入挖掘时,它们处于线程级别。驱动程序需要能够阻止中断以及其他线程以执行某些任务。

面向对象的语言也倾向于反复分配和释放(通过垃圾回收)大量内存。但是,在中断处理程序中,您访问堆分配功能的能力受到严格限制。这是因为堆分配可能触发垃圾回收(昂贵),并且因为您必须避免并处理尝试同时分配中断代码和非中断代码的情况。如果没有对此代码、编译器输出以及管理代码的任何内容(VM或可能是本地编译并仅使用库)施加大量限制,您可能最终会遇到一些非常奇怪的错误。

管理语言必须由某人管理。这种管理可能依赖于一个运行良好的底层操作系统。这为许多(但不是所有)驱动程序使用托管代码产生了引导问题。

完全可以用C#编写设备驱动程序。如果您正在驱动串行设备(例如GPS设备),那么它可能很简单(尽管您将在更低层次上使用UART芯片或USB驱动程序,这可能是用C或汇编编写的),因为可以作为应用程序执行。如果您正在编写以太网卡(不用于网络引导),则理论上可能可以使用C#的某些部分,但您可能会严重依赖其他语言编写的库和/或使用操作系统的用户空间驱动程序功能。

C用于驱动程序,因为其输出相对可预测。如果您了解处理器的一些汇编语言,可以使用C编写一些代码,针对该处理器进行编译,并且可以相当准确地猜测其汇编代码的样子。您还将了解这些指令的确定性。它们中的任何一个都不会让您惊讶并触发垃圾回收器或调用析构函数(或finalize)。


2

因为C#是一种高级语言,它不能直接与处理器通信。C代码可以直接编译成处理器能理解的本地代码。


6
C# 最终会通过间接的方式编译成本地代码。每台计算机都需要通过"间接"的方式被编译成处理器可以理解的东西。 - Earlz
1
@Earlz,作为一名长期从事嵌入式系统和驱动程序的人,让JIT或解释器在我的内核中自由运行的想法让我感到非常不安。我已经足够困扰于确保驱动程序能够满足其延迟要求,而不需要在其中添加那种复杂性。另一方面,我欢迎类似于Windows中的用户模式驱动程序和Linux中的FUSE之类的趋势。 - RBerteig

1

仅仅是为了补充Darin Dimitrov的回答。是的,C#程序无法在内核模式下运行。

但是为什么不能呢?

在Patrick Dussud的interview中,他描述了在Vista开发期间尝试将CLR包含在低级别*的情况。他们遇到的障碍是CLR依赖于操作系统安全库,而这个库又依赖于UI层。他们无法在Vista中解决这个问题。除了Singularity之外,我不知道还有其他任何努力。

*请注意,虽然“低级别”可能不足以让我们能够使用C#编写驱动程序,但至少是必要的。


-1

C语言支持与其他外设的接口更多,因此C语言用于开发系统软件。唯一的问题是需要管理内存,这是开发人员的噩梦。但在C#中,内存管理可以轻松自动完成(C和C#之间有无数差异,请尝试谷歌搜索)。


3
不正确:http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx - Moberg

-1

说实话,那些擅长硬件或硬件接口的人,通常不是非常精通编程。他们倾向于使用像C这样的简单语言。否则,框架将会演变成允许在内核级别使用像C++甚至C#这样的语言。整个操作系统都可以用C++(ECOS)编写。所以,在我看来,这主要是传统。

现在,对于在驱动程序/内核等要求严格的代码中使用更复杂的语言,确实存在一些合理的争论。有可见性方面的问题。C#和C++编译器在幕后做了很多工作。一个无害的赋值语句可能隐藏了大量的代码(运算符重载、属性)。异常的代价可能不太明显。垃圾回收使对象/内存的生命周期不清楚。所有使编程更容易的功能,也是绞索。

然后是语言所需的生态系统。如果所需的功能引入了太多组件,仅仅大小就可能成为一个因素。如果语言中的基元倾向于沉重(为了有用的软件抽象),那么这将是驱动程序和内核可能不愿承担的负担。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接