C Sharp

来自osdev
跳到导航 跳到搜索

请注意,本文的正确标题是C#,但是由于Wiki技术限制,它被写为(也读作) “C Sharp".

C# 是一种面向对象的编程语言,由微软开发,并由ECMA和ISO标准化。 它的语法类似于 C++,但在功能上有显著差异。 它旨在用于创建在Microsoft的.NET基础设施下运行的应用程序。 这里的重点是,它将被编译成一种叫做 CIL 的中间字节码语言,然后被.NET运行时“即时编译”成机器码。 运行时还为代码提供了一些有关垃圾收集,运行时类型信息和动态编译的有用功能。 标准库 (称为mscorlib) 将提供字符串和其他数据结构类 (类似于C++中的stdlib),并调用Windows API进行其他任务 (主要是I/O,GUI以及进程和线程管理)。


为什么用C# 写一个内核?

用C# 编写内核有很多缺点。 首先,需要提供很大一部分的运行时和标准库,以及某种方法将内核转换为机器代码,以允许内核本身运行。 其次,直接内存访问很困难 (尽管并非不可能-有关更多信息,请参见 “不安全” 关键字)。 好处主要是类型和内存安全提供的好处。 给定CIL到本机代码编译器,该编译器按预期工作,并且不使用 'unsafe' 关键字,应该可以编写一个内核,以保证不会访问某些预定义区域之外的代码或数据。 然后,该想法可以扩展到所有用户程序,这将阻止用户程序尝试访问不允许访问的内核区域或其他程序的区域。 这意味着从理论上讲,你可以在同一地址空间中运行所有程序,而无需担心它们意外或恶意地相互干扰,前提是地址空间要足够大。 x86_64提供的扩展地址空间很可能足够大。


将你的内核编译为机器码

有两种方法可以将C# 代码转换为机器码:

1) 编写一个编译器,将C# (或它的超集) 直接转换为机器代码。 这是微软的研究操作系统 Singularity 采用的方法,它定义了 Sing# 语言,以便更容易与底层硬件交互。 Sing# 代码由其编译器 (编译器) Bartok 转换为机器码。

2) 编写一个将CIL转换为机器码的编译器。 这利用了微软.NET或mono项目已经存在的C# 到CIL编译器。 这是许多开源C# 内核所采用的方法,包括 SharpOSCosmos,[mosa-project.org/MOSA项目] 和 tysos

此外,上述两种方法都可以提前 (AOT) 或及时 (JIT)编译。 AOT方法可能是更简单的开始-你有你的编译器运行在你的开发系统上,用于产生可执行文件 (例如 ELF),然后可以直接由标准引导加载器加载。 JIT设计需要在内核之前加载大量代码,然后在运行内核之前将内核转换为机器代码。 这里的问题是JIT编译器可能需要很多服务,只有你的内核才能编译。 最好的组合可能是AOT编译你的内核和JIT编译器并加载它们,然后所有其他进程都可以被JIT编译。

运行时

几个C# 命令 (或它们在CIL中的等效命令) 需要一个运行时 (微软称之为虚拟执行系统或VES)。 例如,'newobj' CIL命令的预期结果是在垃圾管理的堆上创建对象。 这将需要一个malloc函数,然后需要一些方法来对堆上执行gargabe收集。 使用巧妙的编码 (主要使用静态或堆栈定义的对象),可以让你的内核不使用newobj命令,直到你建立了堆和malloc函数。

你还需要为类提供运行时类型信息的封装,并以某种方式实现System.Object.GetType() 和typeof() 函数,以返回语义上等效于System.type的类。


标准库

Mscorlib.dll是.NET运行时的基本组件,并提供所有标准类型的定义 (例如,用于32位有符号整数的System.Int32,用于字符串的System.String,用于类型为 “T” 的对象列表的System.Collections.Generic.List<T>)。 要在内核中编写任何有意义的代码,你可能需要提供其中大多数的实现。 选项有:

1) 尝试用编译器编译微软mscorlib.dll。 我强烈建议任何考虑此问题的人,请在执行此操作之前检查所有法律声明。 你已经被警告过了。

2) 使用 Mono项目 提供的corlib。 请注意,它们实现中的许多函数都标记为 “InternalCall” 或 “PInvoke”。 这些意味着你必须提供该函数的实现,无论是内置的编译器还是由内核提供的。 这个库是相当复杂和庞大的,但是,你需要确保你的编译器为每个函数生成准确的代码 - 单元测试可以很大程度帮助你。

3) 编写自己的基本corlib,仅包含你需要的那些函数。

4) 不要使用corlib库-只要你不尝试在内核中使用其中包含的任何函数,就可以了。 没有什么好叙述的,因为你使用C# 编写你的内核,你必须使用corlib库。


总结

虽然可以在C# 中编写内核 (正如上面列出的许多项目所证明的那样),但它不是 (目前) 可以快速完成的事情。 你将需要内核,编译器,运行时和标准库的组合来使其正常运行。 但是,一旦达到足够的成熟度,就可以重新使用上面列出的许多项目中使用的编译器和标准库,因此,你需要做的就是编写内核和一些内存管理功能。 但是请注意,这些项目中使用的大多数提前编译器都与它们用于开发的操作系统紧密相关。 如果你选择编写自己的编译器,请注意: 解释 语言 - 编写一个编译器与编写一个操作系统内核一样困难。

它不是那么简单的部分原因是所有当前的C# 编译器输出MSIL或.NET字节码,这涉及将其转换为机器代码的额外步骤。 但是,从理论上讲,有一天有人可能会为GCC实现C# 前端 (因此你可以直接用GCC编译出原始机器代码),这将是一个完全不同的故事。

另见

文章

外部链接

  • C# on Wikipedia