tiny.box.show_将具有15年历史的.NET 1.1虚拟CPU Tiny操作系统学校项目移植到.NET Core 2.0

tiny.box.show

tiny.box.show

I've had a number of great guests on the podcast lately. One topic that has come up a number of times is the "toy project." I've usually kept mine private - never putting them on GitHub - Somewhat concerned that people would judge me and my code. However, hypocrite that am (aren't we all?) I have advocated that others put their "Garage Sale Code" online. So here's some crappy code. ;)

最近,我在播客上有很多很棒的客人。 “玩具项目”是一个经常出现的话题。 我通常将自己的隐私保密-从未将它们放到GitHub-有点担心人们会判断我和我的代码。 但是,伪君子是(不是所有人吗?)我主张其他人将他们的“车库销售代码”放在网上。 所以这是一些糟糕的代码。 ;)

序言 (The Preamble )

While I've been working as an engineer for 25 years this year, I didn't graduate from school with a 4 year degree until 2003 - I just needed to get it done, for myself. I was poking around recently and found my project from OIT's CST352 "Operating Systems" class. One of the projects was to create a "Virtual CPU and OS." This is kind of a thought exercise. It's not really a parser/lexer - although there is both - and it's not a real OS. But it needs to be able to take in a made-up quasi-Assembly Language instruction set and execute them on a virtual CPU while managing virtual memory of arbitrary size. Again, a thought exercise made real to confirm that the student understands the responsibilities of a CPU.

今年我已经担任工程师25年,但直到2003年我才从学校毕业,获得了4年的学位-我只是需要自己完成这项工作。 我最近在闲逛,发现我的项目来自OIT的CST352“操作系统”类。 其中一个项目是创建“虚拟CPU和操作系统”。 这是一种思想练习。 它实际上不是解析器/词法分析器-尽管两者都有-而且它不是真正的OS。 但是它需要能够接受一个伪造的准汇编语言指令集并在虚拟CPU上执行它们,同时管理任意大小的虚拟内存。 同样,进行了一次思考练习,以确认学生了解CPU的职责。

Here's an example "application." Confused yet? Here's the original spec I was given in 2002 that includes the 36 instructions the "CPU" should understand. It has 10 general-purpose 32bit registers address as 1 through 10. Register 10 is the stack pointer. There are two bit flag registers - sign flag and zero flag.

这是一个示例“应用程序”。 感到困惑了吗? 这是我在2002年给出原始规格,其中包括“ CPU”应理解的36条指令。 它有10个通用32位寄存器地址,范围从1到10。寄存器10是堆栈指针。 有两个位标志寄存器-符号标志和零标志。

Instructions are "opcode arg1 arg2" with constants prefixed with "$."

指令是带有前缀“ $”的常量“ opcode arg1 arg2”。

11 r8        ;Print r8
6 r1 $10 ;Move 10 into r1
6 r2 $6 ;Move 6 into r2
6 r3 $25 ;Move 25 into r3
23 r1 ;Acquire lock in r1 (currently 10)
11 r3 ;Print r3 (currently 25)
24 r1 ;Release r1 (currently 10)
25 r3 ;Sleep r3 (currently 25)
11 r3 ;Print r3 (currently 25)
27 ;Exit

I write my homework assignment in 2002 in the idiomatic C# of the time on .NET 1.1. That means no Generics<T> - I had to make my own strongly typed collections. That means C# has dozens of (if not a hundred) language and syntax improvements. I didn't use a Unit Testing Framework as TDD was just starting around 1999 during the XP (eXtreme Programming) days and NUnit was just getting start. It also uses "unsafe" to pin down memory in a few places. I'm sure there are WAY WAY WAY better and more sophisticated ways to do this today in idiomatic C# of 2017. Those are excuses, the real reasons are my own ignorance, ability, combined with some night-school laziness.

我在2002年用当时惯用的C#在.NET 1.1上编写作业。 这意味着没有Generics <T>-我必须创建自己的强类型集合。 这意味着C#具有数十种(如果不是一百种)语言和语法改进。 我没有使用单元测试框架,因为TDD只是在XP(极限编程)期间的1999年左右才开始,而NUnit才刚刚开始。 它还在少数地方使用“不安全”锁定内存。 我敢肯定,今天在2017年的C#中,有一些方法可以做得更好,更复杂。这些都是借口,真正的原因是我自己的无知,能力和夜校的懒惰。

One of the more fun parts of this exercise was moving from physical memory (a byte array as I recall) to a full-on Memory Manager where each Process thought it could address a whole bunch of Virtual Memory while actual Physical Memory was arbitrarily sized. Then - as a joke - I would swap out memory pages as XML! ;) Yes, to be clear, it was a joke and I still love it.

此练习中最有趣的部分之一是从物理内存(我记得一个字节数组)转移到一个全功能的内存管理器,在该管理器中,每个进程都认为它可以寻址整个虚拟内存,而实际物理内存的大小却可以任意设置。 然后-开个玩笑-我将存储页面换成XML! ;)是的,很明显,这只是个玩笑,我仍然喜欢它。

You can run an "app" by passing in the total physical memory along with the text file containing the program, but you can also run an arbitrary number of programs by passing in an arbitrary number  of text files! The "TinyOS" will handle each process thinking it has its own memory and will time

您可以通过传入总物理内存以及包含该程序的文本文件来运行“应用程序”,但是也可以通过传入任意数量的文本文件来运行任意数量的程序! “ TinyOS”将处理每个进程,认为它具有自己的内存并会计时

If you are more of a visual learner, perhaps you'd prefer this 20-slide PowerPoint on this Tiny CPU that I presented in Malaysia later that year. You dig those early 2000-era slides? I KNOW YOU DO.

如果您是一名视觉学习者,那么您可能更喜欢那年晚些时候在马来西亚展示的Tiny CPU上的20张幻灯片。 您是否挖掘了2000年代早期的幻灯片? 我知道你知道

Tiny OS Memory Slides
Tiny OS Memory Slides
Tiny OS Memory Slides

将.NET 1.1应用程序更新为跨平台的.NET Core 2.0(Updating a .NET 1.1 app to cross-platform .NET Core 2.0)

Step 1 was to download the original code from my own blog. ;) This is also Reason #4134 why you should have a blog.

步骤1是从我自己的博客中下载原始代码。 ;)这也是为什么您应该拥有博客的#4134原因

I decided to use Visual Studio 2017 to upgrade it, and even worse I decided to use .NET Core 2.0 which is currently in Preview. I wanted to use .NET Core 2.0 not just because it's cross-platform but also because it promises to have a pretty large API surface area and I want this to "just work." The part about getting my old application running on Linux is going to be awesome, though.

我决定使用Visual Studio 2017对其进行升级,更糟糕的是,我决定使用当前在Preview中的.NET Core 2.0。 我想使用.NET Core 2.0不仅是因为它是跨平台的,而且还因为它承诺具有相当大的API表面积,我希望它能够“正常工作”。 但是,有关使我的旧应用程序在Linux上运行的部分将非常棒。

Visual Studio then pops a scary dialog about upgrading files. NOTE that another totally valid way to do this (that I will end up doing later in this blog post) is to just make a new project and move the source files into it. Natch.

然后,Visual Studio弹出一个有关升级文件的可怕对话框。 注意,另一种完全有效的方法(我将在本博客文章的稍后部分中完成)只是创建一个新项目并将源文件移入其中。 纳奇

image

Visual Studio says it's targeting .NET 2.0 Full Framework, but I ratchet it up to 4.6 to see what happens. It builds but with a bunch of errors about Obsolete methods, the most interesting one being this one:

Visual Studio表示它的目标是.NET 2.0完整框架,但我将其提高到4.6以了解会发生什么。 它可以构建,但是存在一些关于过时方法的错误,其中最有趣的是这个:

Warning CS0618    
'ConfigurationSettings.AppSettings' is obsolete:
'This method is obsolete, it has been replaced by
System.Configuration!System.Configuration.ConfigurationManager.AppSettings'
C:\Users\scott\Downloads\TinyOSOLDOLD\OS Project\CPU.cs 72

That's telling me that my .NET 1/2 API will work but has been replaced in .NET 4.x, but I'm more interested in .NET Core 2.0. I could make my EXE a LIB and target .NET Standard 2.0 or I could make a .NET Core 2.0 app and perhaps get a few more APIs. I didn't do a formal analysis with the .NET Portability Analyzer but I will add that to the list of Things To Do. I may be able to make a library that works on an iPhone - a product that didn't exist when I started this assignment. That would be Just Cool(tm).

这告诉我我的.NET 1/2 API可以使用,但是在.NET 4.x中已被替换,但是我对.NET Core 2.0更加感兴趣。 我可以使我的EXE成为LIB并以.NET Standard 2.0为目标,或者我可以使.NET Core 2.0应用成为可能,并获得更多的API。 我没有使用.NET Portability Analyzer进行正式分析,但会将其添加到“要做的事情”列表中。 我也许可以制作一个可以在iPhone上使用的库,这是我开始这项作业时不存在的产品。 那就是Just Cool(tm)。

I decided to just make a new empty .NET Core 2.0 app and copy the source .cs files into it. A few interesting things.

我决定只制作一个新的空.NET Core 2.0应用程序并将源.cs文件复制到其中。 一些有趣的事情。

  • My app also used "unsafe" code (it pins memory down and accesses it directly).

    我的应用程序还使用了“不安全”代码(它将内存固定下来并直接访问它)。
  • It has extensive inline documentation in comments that I used to use NDoc to make a CHM Help file. I'd like that doc to turn into HTML at some point.

    它在注释中包含大量内联文档,我曾经使用NDoc来制作CHM帮助文件。 我希望该文档在某个时候能够转换为HTML。
  • It also has an appsettings.json file that needs to get copied to the output folder when it compiles.

    它还有一个appsettings.json文件,需要在编译时将其复制到输出文件夹。
  • While I could publish it to a self-contained .NET Core exe, for now I'm running it like this in my test batch files - example:

    虽然我可以将其发布到一个自包含的.NET Core exe中,但现在我在测试批处理文件中以这种方式运行它-例如:

    • dotnet netcoreapp2.0/TinyOSCore.dll 512 scott13.txt

      dotnet netcoreapp2.0 / TinyOSCore.dll 512 scott13.txt

    While I could publish it to a self-contained .NET Core exe, for now I'm running it like this in my test batch files - example:

    虽然我可以将其发布到一个自包含的.NET Core exe中,但现在我在测试批处理文件中以这种方式运行它-例如:

Here's the resulting csproj file.

这是生成的csproj文件。

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<None Remove="appsettings.json" />
</ItemGroup>

<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0-preview2-final" />
</ItemGroup>

</Project>

Other than the obsolete configuration warning and a few malformed XML comments, the app compiled and ran! You can actually "watch" the nightmare process here https://github.com/shanselman/TinyOS/commits/Core2Port in the form of GitHub commits. I also moved the docs from a 2002 Word Doc to Markdown so be sure to explore the fairly extensive spec https://github.com/shanselman/TinyOS.

除了过时的配置警告和一些格式错误的XML注释之外,该应用还可以编译并运行! 实际上,您可以在https://github.com/shanselman/TinyOS/commits/Core2Port上以GitHub提交的形式“监视” 噩梦 过程。 我还将文档从2002 Word文档移至Markdown,因此一定要浏览相当广泛的规范https://github.com/shanselman/TinyOS

The only significant change was loading the config. Configuration is even more different on .NET Core 2.0 than Full Framework. It's FAR more, ahem, configurable. I could have used "Options," I could have written my own config provider if it was important to keep the file format.

唯一的重大更改是加载配置。 .NET Core 2.0上的配置与Full Framework相比有很大不同。 远非如此,可配置。 如果保留文件格式很重要,我本可以使用“ Options ”来编写自己的配置提供程序。

This little TinyOS has a bunch of config options that come in from a .exe.config file in XML like this (truncated):

这个小的TinyOS有很多配置选项,这些配置选项来自XML的.exe.config文件,如下所示(已截断):

<configuration>
<appSettings>
<!--
Must be a factor of 4
This is the total Physical Memory in bytes that the CPU can address.
This should not be confused with the amount of total or addressable memory
that is passed in on the command line.
-->
<add key="PhysicalMemory" value="128" />
<!--
Must be a factor of 4
This is the ammount of memory in bytes each process is allocated
Therefore, if this is 256 and you want to load 4 processes into the OS,
you'll need to pass a number > 1024 as the total ammount of addressable memory
on the command line.
-->
<add key="ProcessMemory" value="384" />
<add key="DumpPhysicalMemory" value="true" />
<add key="DumpInstruction" value="true" />
<add key="DumpRegisters" value="true" />
<add key="DumpProgram" value="true" />
<add key="DumpContextSwitch" value="true" />
<add key="PauseOnExit" value="false" />

I have a few choices. I could make a Configuration Provider and reach .NET Core to read this format (there's an XML adapter, in fact) or make the code porting easier by moving these "name/value" pairs to a JSON file like this:

我有几种选择。 我可以制作一个配置提供程序并到达.NET Core以读取这种格式(实际上是一个XML适配器),或者通过将这些“名称/值”对移动到这样的JSON文件中来简化代码移植:

{
"PhysicalMemory": "128",
"ProcessMemory": "384",
"DumpPhysicalMemory": "true",
"DumpInstruction": "true",
"DumpRegisters": "true",
"DumpProgram": "true",
"DumpContextSwitch": "true",
"PauseOnExit": "false",
"SharedMemoryRegionSize": "16",
"NumOfSharedMemoryRegions": "4",
"MemoryPageSize": "16",
"StackSize": "16",
"DataSize": "16"
}

This was just a few minutes of search and replace to change the XML to JSON. I could have also written a little app or shell script. By changing the config (rather than writing an adapter) I could then keep the code 99% the same.

搜索和替换只需几分钟,即可将XML更改为JSON。 我还可以编写一个小应用程序或Shell脚本。 通过更改配置(而不是编写适配器),我可以将代码保持99%相同。

My code was doing things like this (all over...there was no DI container yet):

我的代码正在做这样的事情(遍...还没有DI容器):

bytesOfPhysicalMemory = uint.Parse(ConfigurationSettings.AppSettings["PhysicalMemory"]);

And I'd like to avoid major refactoring - yet. I added this bit of .NET Core configuration at the top of the EntryPoint and saved away an IConfigurationHost:

而且我想避免重大重构-到目前为止。 我在EntryPoint的顶部添加了.NET Core配置,并保存了IConfigurationHost:

var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json");
Configuration = builder.Build();

I've got a Dictionary in the format of the IConfiguration host called "Configuration." So now I just do this in a dozen places and the app compiles again:

我有一个IConfiguration主机格式的字典,称为“配置”。 所以现在我只是在十几个地方执行此操作,然后应用再次编译:

bytesOfPhysicalMemory = uint.Parse(Configuration["PhysicalMemory"]);

This brings up that feeling we all have when we look at old code - especially our own old code. I should have abstracted that away! Why didn't I use an interface? Why so many statics? What was I thinking?

当我们看旧代码-尤其是我们自己的旧代码时,这会带给我们所有人一种感觉。 我本该把它抽象化! 为什么不使用界面? 为什么会有这么多静数? 我在想什么

We can beat ourselves up or we can feel good about ourselves and remember this. The app worked. It still works. There is value in it. I learned a lot. I'm a better programmer now. I don't know how far I'll take this old code but I had a lovely afternoon porting it to .NET Core 2.0 and I may refactor the heck out if it or I may not.

我们可以殴打自己,也可以自我感觉良好并记住这一点。 该应用程序正常运行。 它仍然有效。 有价值。 我学到了很多。 我现在是一个更好的程序员。 我不知道我会把这段旧代码带走多远,但是我度过了一个愉快的下午,将其移植到.NET Core 2.0,因此我可以重构它,否则我可以重构它

TinyOS on Ubuntu

For now I did update the smoke tests to run on both Windows and Linux and I'm happy with the experiment.

现在,我确实将烟雾测试更新为可以在Windows和Linux上运行,并且对此实验感到满意。

相关链接 (Related Links)

Have YOU done a project like this, either in school or on your own?

您在学校还是自己完成了这样的项目?

翻译自: https://www.hanselman.com/blog/porting-a-15-year-old-net-11-virtual-cpu-tiny-operating-system-school-project-to-net-core-20

tiny.box.show

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值