[原文发表地址] The Weekly Source Code 15 - Tiny Managed Operating System Edition
[原文发表时间] 2008-02-04 11:17PM
感谢Thijs Kroesbergen给了这周源代码的灵感。他让我对一个用C#写成的微型操作系统有了浓厚的兴趣,这个系统叫做“Cosmos(C#开放源托管操作系统)。和项目显示的那样,为什么呢?因为它很有趣。我曾在晚上去学校的时候带了个操作系统类,然后用C#给这个类写了微型的虚拟操作系统。
所以,亲爱的读者,我在这里奉上第15篇“每周源代码。” 之后还会继续。这里给大家一些我这周在读的资源。
首先,我回去看了看我的微型操作系统项目中的源代码。基本都是在晚上用.NET 1.1写成的。这些代码相当于一个10周(一个学期)的项目,为了把其他的周期空出来,我在一个周末之内就把这些全写掉了。
读以前的代码真的是很恐怖的事情。我敢断言,如果你翻看你以前写的代码,觉得还感觉很好的话,要么就是你疯了,要么走火入魔了,要么你就是个真正优秀的程序员。一定是这三种里的一种。
要记得这个项目是一个微型虚拟操作系统。我们给小处理器设置了指令集,给程序添加了格式,我们的目的则是要写一个操作系统来运行他们。
以下是我的MemoryManager的构造器。我在构造器里动足了脑筋。我做了很多有趣的小事情,其中一个就是在这个微型操作系统中,利用 XML文件来实现内存页面交换。这只是个小小的玩笑,因为XML对于细致如内存管理器的程序来说,。显得太臃肿和 庞大了.我想既然在用像.NET这类高端的应用模拟操作系统行为,那为什么我不能以XML形式来交换内存到磁盘呢?
我希望为这个微型虚拟操作系统的源代码可以像我们在操作系统书籍中寻找的那种伪代码一样。
回头看看,我觉得如果我做一个WinForms主机,做一个内存可视,让大家可以看到像内存碎片这样的东西,可能会更酷些。也许我会在WPF或者以XBAP的形式做一个出来,这会成为与我交谈过的学生们一个很棒的学习工具。
public MemoryManager(uint virtualMemSizeIn)
{
// Find a size for addressableMemory that is on a page boundary
virtualMemSize = CPU.UtilRoundToBoundary(virtualMemSizeIn, CPU.pageSize);
// Size of memory must be a factor of CPU.pageSize
// This was asserted when the CPU initialized memory
uint physicalpages = (uint)(CPU.physicalMemory.Length/CPU.pageSize);
uint addressablepages = (uint)(virtualMemSize/CPU.pageSize);
_pageTable = new ArrayList((int)addressablepages);
// Delete all our Swap Files
foreach (string f in Directory.GetFiles(".","*.xml"))
File.Delete(f);
// For all off addressable memory...
// Make the pages in physical and the pages that aren't in physical
for (uint i = 0;i < virtualMemSize; i+=CPU.pageSize)
{
// Mark the Pages that are in physical memory as "false" or "not free"
MemoryPage p;
if (i < CPU.physicalMemory.Length)
{
p = new MemoryPage(i, true);
freePhysicalPages[(int)(i/CPU.pageSize)] = false;
}
else p = new MemoryPage(i, false);
_pageTable.Add(p);
}
}
显然,我的操作系统不过是个小点缀。Cosmos,从某些方面来说,超级有趣。怎么能创建一个真正的操作系统(指的是真正可以在硬件上启动的操作系统,不管是虚拟或者物理的),用中间语言??当然是把中间语言翻译成汇编代码,很酷而且超级聪明。
Cosmos包含一个能阅读输入文件(通常是shell)编译器(IL2CPU,作为Cosmos的一部分)和Cosmos库,可以将IL编译成x86代码。IL2CPU有跨平台的层,我们计划支持其他处理器和平台,包括x64。IL2CPU还支持一些扩展函数,使得C#代码能直接与CPU、注册器以及内核端口交互。IL2CPU包含了一些内联汇编程序,不过没有ASM文件需要相链接。
目前IL2CPU首先输出原始ASM文件(携带IL注释),然后用nasm(免费的汇编程序)进行处理。之后我们计划要省却这些直接换到二进制。
Cosmos适用的场景也非常有趣。因为它易写易建,你可以创建带任何你想要的功能的小的迷你操作系统。你可以创建只做DNS的操作系统,或者只做REST服务的操作系统。谁知道呢。(是的,我知道你也可以做一个精简的Linux)。还有我们也有讨论让Cosmos在Wii上运行。
下列实例来自于Indy.IL2CPU.Assembler.X86.Native,你可以看到,IL2CPU写出了ASM。
protected override void EmitDataSectionHeader(string aGroup, StreamWriter aOutputWriter) {
base.EmitDataSectionHeader(aGroup, aOutputWriter);
if (aGroup == MainGroup) {
aOutputWriter.WriteLine("section .data");
aOutputWriter.WriteLine("_start: ");
aOutputWriter.WriteLine("; multiboot header ");
aOutputWriter.WriteLine("MBFLAGS equ 0x03 ; 4KB aligned modules etc., full memory info, ");
aOutputWriter.WriteLine(" ; use special header (see below) ");
aOutputWriter.WriteLine("dd 0x1BADB002 ; multiboot signature ");
aOutputWriter.WriteLine("dd MBFLAGS ; 4kb page aligment for modules, supply memory info ");
aOutputWriter.WriteLine("dd -0x1BADB002-MBFLAGS ; checksum=-(FLAGS+0x1BADB002) ");
aOutputWriter.WriteLine("; other data - that is the additional (optional) header which helps to load ");
aOutputWriter.WriteLine("; the kernel. ");
aOutputWriter.WriteLine("; end of header ");
aOutputWriter.WriteLine("MultiBootInfo_Memory_High dd 0");
aOutputWriter.WriteLine("MultiBootInfo_Memory_Low dd 0");
}
有很多像这样的函数在做这样的工作。不过编排是在Engine.cs上的,组件通过反射出现,他们的函数通过以下明显的代码被区分了(我的伪代码):
foreach Type in Assembly
foreach Method in Type
ProcessMethod into ASM (via ProcessAllMethods)
这里使用了有趣的ILReader,这个类本身非常有用。这里提供一部分修剪后的ProcessAllMethods代码,这些代码使用了ILReader。
到这里,我们加载了一个程序集,获取了一个类型,得到了xCurrentMethod函数。他们得到函数,添加一些例外处理(我去除了这些,非常繁琐),然后获得了OpCode,然后用目前的汇编程序整合运算。涂上肥皂,清洗,重复必要的。
ILReader xReader = new ILReader(xCurrentMethod);
while (xReader.Read()) {
if (mInstructionsToSkip > 0) {
mInstructionsToSkip--;
continue;
}
ExceptionHandlingClause xCurrentHandler = null;
...snip...
xMethodInfo.CurrentHandler = xCurrentHandler;
xOp = GetOpFromType(mMap.GetOpForOpCode(xReader.OpCode), xReader, xMethodInfo);
if ((!xOp.SupportsMetalMode) && mAssembler.InMetalMode) {
throw new Exception("OpCode '" + xReader.OpCode + "' not supported in Metal mode!");
}
xOp.Assembler = mAssembler;
new Comment("StackItems = " +
mAssembler.StackContents.Count + ",
Top item = " +
(mAssembler.StackContents.Count > 0 ? mAssembler.StackContents.Peek().ToString() : "(empty)"));
xOp.Assemble();
}
Cosmos项目中注释不是很多,但是一旦你搞清楚他们在干什么了,那就是非常赞的工作了,我能明白为什么他们在做的时候那么享受了。
他们的网站http://www.gocosmos.org上说:
若只是想玩玩Cosmos:
1. 安装用户组件。
2. 加入讨论列表。
其他资源:
1. 浏览常见问题。
2. 注册Cosmos博客。
3. 文档 —— 开发者文档。
如果你对内核开发感兴趣:
1. 从CodePlex上获取资源。
2. 仔细阅读所有的要求。都是些基础,所有你需要的都是免费的,除了Windows(为开发考虑)。
3. 阅读新手入门。
希望你喜欢!