月度归档:2019年01月

长模式与 16 位程序

这是我在知乎的回答:https://www.zhihu.com/question/310785889/answer/58670983

首先我们要把 16 位程序分成两类来看:跑在实模式下的 16 位程序和跑在保护模式下的 16 位程序。长模式是支持兼容 16 位的保护模式的(x86-64 白皮书):

但由于在长模式下移除了虚拟 8086 模式,无法运行实模式的(直接访问硬件的)16位程序。

至于为什么移除了虚拟 8086 模式,只能认为是不想再多背包袱了。已经有的包袱甩不掉,但至少别给自己再找新麻烦…

其实 Intel 在 80286 添加保护模式时就不想带这个包袱了,它没有提供直接的方法从保护模式转换回实模式(即无法支持实模式 16 位程序) 。也许是大家怨声载道,而后在 386 中 Intel 添加了虚拟 8086 模式,允许直接在保护模式下虚拟一个实模式出来。这样在 32 位操作系统中,实模式的 16 位程序才能运行。所以到了 64 位,这样的包袱不再扔一次怎么行呢,实在不行再把它加回来就好了,毕竟这事 Intel 已经干过一回了 🤣

总而言之,长模式是可以运行 16 位程序的,但只兼容保护模式。不过 Windows 也无法运行 16 位保护模式下的程序,这是 Windows 本身不再支持了的原因,不是长模式的限制。

错误模型 – The Error Model

  • 原文链接:http://joeduffyblog.com/2016/02/07/the-error-model/
  • 作者:Joe Duffy
  • 翻译:dontpanic

译注:下文中所有的“我”、“我们”均指代原作者 Joe Duffy 或其所在团队。作者总结了目前主流编程语言中常见的错误模型的优缺点,同时分别给出了自己的针对不可恢复错误(Unrecoverable Error)和可恢复错误(Recoverable Error)的处理方案。由于本文有一些惯用语和专业词语,受限于我的水平,可能出现翻译错误、或措辞与主流方案不同等问题,欢迎指出以便修正。本文较长,请做好长时间阅读的准备。

译注:前情提要:原作者 Joe Duffy 曾在微软参与开发一款操作系统 Midori,这是一款研究型/孵化型项目。这款操作系统主要由一种 C# 的变种语言(有人称作 M# 语言)编写。

The Error Model

Midori 使用了一种基于 C# 的、支持 AOT 编译、类型安全的语言。除了我们的微内核,整个系统都是使用这种语言编写的,包括驱动程序、域内核(Domain Kernel),以及全部的用户代码。我在这段时间里收获了很多,现在是时候总结一下了。整个语言涵盖的东西太多了,我会分成几篇文章来阐述,就先从错误模型开始。错误(Errors)的传递与处理在任何编程语言中都是非常基础的部分,而对于用来编写高可靠操作系统的语言来说更是如此。就像 Midori 项目的其他部分一样,任何修改一部分都应该从全局的角度来考量,并进行不断地迭代。我经常从原来的同事那里听到说,错误模型是他们在 Midori 上开发程序时最怀念的部分。我也很怀念这部分。那么废话少说,我们这就开始。

错误模型简介

错误模型需要回答的最基本的问题是:“错误”应该如何传达给程序员和用户?这问题似乎很简单。

要回答这个问题,最大的阻碍之一是:如何定义什么是“错误”。很多语言把 Bug 和可恢复错误归为一类,用同样的机制来处理,比如把空指针引用错误、数组访问越界错误与网络连接错误、语法分析错误混为一谈。这种一致性初看起来很美好,但它有着深层次的问题——这种一致性会造成很大误解,并且通常会导致程序员写出不可靠的代码。

总的来说,我们的解决方法是同时提供两套错误模型。一方面,对于程序的 Bug,我们提供了快速失败(Fail-Fast)模型,在 Midori 中我们称其为放弃(Abandonment);另一方面,对于可恢复的错误,我们也提供了静态受检查异常(Statically Checked Exception)。这两种错误模型从编程模式到背后的机制都截然不同。放弃会无条件地立即终止整个进程,不会再运行任何用户代码(需要说明的是:一个典型的 Midori 程序会由很多个小的、轻量级的进程组成);异常则允许恢复用户代码的执行,在这个过程中类型系统会起到重要的检查和验证的作用。

我们的旅程漫长而曲折。为了讲好这段故事,这篇文章分为以下6个主要部分:

  • 野心和经验
  • Bugs 不是可恢复错误!
  • 可靠性、容错性和隔离性
  • Bugs:放弃(Abandonment)、断言(Assertions)和合约(Contracts)
  • 可恢复错误:类型导向的异常
  • 回顾与总结

现在看来,有些结论似乎很明显,尤其是在更现代的系统语言
(比如 Go 和 Rust)出现之后。但是一些结论还是让我们很惊讶。我会尽量省略废话,但也会提供足够的背景故事。我们走过很多弯路,但我觉得这些弯路甚至要比最终的结论更有趣。

继续阅读