“Beginner Mistakes”的版本间差异
(未显示同一用户的1个中间版本) | |||
第1行: | 第1行: | ||
“编写自己的操作系统”的想法把你带到了这里。 本维基网站希望能在你的工作中给你帮助、指点和参考。 | “编写自己的操作系统”的想法把你带到了这里。 本维基网站希望能在你的工作中给你帮助、指点和参考。 | ||
但是,新来者对主题涉及的内容犯某些错误或有共同的误解是很常见的。 这并不是坏事 —— | 但是,新来者对主题涉及的内容犯某些错误或有共同的误解是很常见的。 这并不是坏事 —— 许多人以前犯过同样的起步错误,将来也会犯。 本文章正是为了确保你在深入学习本维基网站所提供的信息之前理解自己要做的事情。 | ||
== 这不是什么 == | == 这不是什么 == | ||
第15行: | 第15行: | ||
=== 一个残酷的真相 === | === 一个残酷的真相 === | ||
''''' | '''''就算拥有多年在各种语言和环境中开发丰富经验的开发人员,在做操作系统开发前仍需要三思。 十多年的编程,包括几年汇编语言和/或系统语言(如C)的低级编码,才是理解操作系统开发的最低要求''''' | ||
更重要的是,随着不同的“标准”、计算机和移动设备型号、外围设备和设计概念的数量不断扩大,开发操作系统的背景门槛越来越高。 | 更重要的是,随着不同的“标准”、计算机和移动设备型号、外围设备和设计概念的数量不断扩大,开发操作系统的背景门槛越来越高。 | ||
对于像丹尼斯·里奇(Dennis Ritchie)、理查德·格林布拉特(Richard Greenblatt)、加里·基尔德尔(Gary Kildall)或史蒂夫·沃兹尼亚克(Steve | 对于像丹尼斯·里奇(Dennis Ritchie)、理查德·格林布拉特(Richard Greenblatt)、加里·基尔德尔(Gary Kildall)或史蒂夫·沃兹尼亚克(Steve Wozniak)这样的早期伟人来说,为硬件编写一个简单的操作系统是另一回事。那时他们已经非常了解当时的机器,操作系统相对简单,并且没有标准规范要遵守,也没有旧标准规范需要来保持向后兼容性。 这在当前一代新老硬件上已不再适用。 此外,他们每个人都已经是一名经验丰富的工程师,已经做了多年的系统编程。 即使在那个时代,它们也只是为系统提供了基础结构; 在系统的核心 (用现代行话来说是内核) 到位之后,大部分工作是由一批后续开发人员完成的。 | ||
这个现象可能也有例外,但并不多;不要指望自己就是那个千里挑一的人。 如果你认为你是,请阅读[https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect 邓宁-克鲁格效应],再重新考虑这件事。 | 这个现象可能也有例外,但并不多;不要指望自己就是那个千里挑一的人。 如果你认为你是,请阅读[https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect 邓宁-克鲁格效应],再重新考虑这件事。 | ||
哦,郑重声明,Linus Torvalds也并不是万众无一的天才 -- 他在编写linux内核时是一名研究生,并且已经使用C进行了多年编码。 虽然他离十几年的标准还差得很远,但作为一名研究生,他把自己的爱好变成了他的硕士论文,他比大多数人投入更多的时间从事这个项目。 不管怎么说,他在1991年向USENET发布著名的“Linux0.0.1”版本只不过是一个循环调度程序,远远谈不上是一个完整的系统。 而达到这一点花了他一年的时间。 明白了吗? | |||
虽然这个维基的大多数贡献者确实很早就开始尝试操作系统开发了,但对我们大多数人来说,这是一个由于缺乏经验而产生的错误。 这个小组的大多数先驱者甚至不知道一个小型OS项目的规模和复杂性,也不知道他们正在进入什么领域。 这是一个难以下咽的苦药,尤其是在像这个维基这样的资源被广泛使用'''以前'''。 我们不能强迫你们从我们的错误中吸取教训,但至少我们可以传递这个警告。 | 虽然这个维基的大多数贡献者确实很早就开始尝试操作系统开发了,但对我们大多数人来说,这是一个由于缺乏经验而产生的错误。 这个小组的大多数先驱者甚至不知道一个小型OS项目的规模和复杂性,也不知道他们正在进入什么领域。 这是一个难以下咽的苦药,尤其是在像这个维基这样的资源被广泛使用'''以前'''。 我们不能强迫你们从我们的错误中吸取教训,但至少我们可以传递这个警告。 | ||
第30行: | 第30行: | ||
=== 是否有关于...的教程? === | === 是否有关于...的教程? === | ||
因为这个地方不能也不适合初学者开发人员,所以经常会有人问起:在其它地方是否有提供更好的解释或易于理解的教程读物。 然而,'''它们不存在'''。 困难的学科不能用轻松的散文来描述,就像世上很多东西太复杂了,作为猴子是无法成功学会的一样。 如果你在阅读官方文档时遇到问题,那么这恰恰是练习的好时机。 | |||
事实上,目前绝大多数的教程都存在一点两点的问题,所以你最好不要一开始就相信它们。 | 事实上,目前绝大多数的教程都存在一点两点的问题,所以你最好不要一开始就相信它们。 | ||
第55行: | 第55行: | ||
===假设它不会有任何结果=== | ===假设它不会有任何结果=== | ||
与上述相反,有些人认为他们的操作系统将毫无用处。 由于这个原因,他们的项目有丑陋的代码,重要的方面不考虑,通常依赖丑陋的黑客式技巧。 最糟糕的是,他们做出的决策不会带来可用性和可扩展性。 这样,他们的假设就变成了一个自我实现的预言。 | |||
实际上,虽然让操作系统在测试机器之外运行的可能性很低,但从这个社区开始的高级操作系统项目有很多了。 | |||
===避免无知=== | ===避免无知=== | ||
初学者经常问 “做X的“ 最容易 ”的方法是什么?” 而不是 “做X的最佳,适当,正确的方法是什么?” 这是危险的,因为新手不会花时间去理解实现某个东西的更好方法,而是从教程中选择概念上更简单的方法。 事实上,更简单的路线往往“太简单”,从长远来看,最终会造成更多问题,因为初学者对更好的替代方案一无所知,也不知道什么时候换更好。 走难走的路又有什么不好? | 初学者经常问 “做X的“ 最容易 ”的方法是什么?” 而不是 “做X的最佳,适当,正确的方法是什么?” 这是危险的,因为新手不会花时间去理解实现某个东西的更好方法,而是从教程中选择概念上更简单的方法。 事实上,更简单的路线往往“太简单”,从长远来看,最终会造成更多问题,因为初学者对更好的替代方案一无所知,也不知道什么时候换更好。 走难走的路又有什么不好? | ||
常见的例子包括懒得使用[[GCC Cross-Compiler|交叉编译器]],不理解[[Real Mode|实模式]]、[[Unreal Mode|非实模式]]、[[Protected Mode|保护模式]],以及[[Long Mode]],从一个点到另一个点跳得太快,而没有首先了解如何收集所有重要配置并充分利用其所有功能(尤其是在引导和初始化期间使用BIOS检测基本功能),依赖于非标准的[[BIOS]]调用,不学习在自己的操作系统以及Windows和Linux下编写硬件驱动程序以获得最大的便利,在全球范围内公开测试功能,使用简单二进制文件而不是[[ELF]] | 常见的例子包括懒得使用[[GCC Cross-Compiler|交叉编译器]],不理解[[Real Mode|实模式]]、[[Unreal Mode|非实模式]]、[[Protected Mode|保护模式]],以及[[Long Mode]],从一个点到另一个点跳得太快,而没有首先了解如何收集所有重要配置并充分利用其所有功能(尤其是在引导和初始化期间使用BIOS检测基本功能),依赖于非标准的[[BIOS]]调用,不学习在自己的操作系统以及Windows和Linux下编写硬件驱动程序以获得最大的便利,在全球范围内公开测试功能,使用简单二进制文件而不是[[ELF]],不学习可执行文件、归档文件、图形、文档和其它文件格式以及压缩算法,等等。 有经验的开发人员使用更好的替代方案是有原因的,你可能还不明白这一点。 经验丰富的开发人员在某些情况下选择使用劣质方法,但这是因为他们可以仔细分析它是否合适,并且知道何时 “不” 使用它。 作为一名初学者或中级开发人员,你可能不太了解这些方法和技术,无法判断劣质解决方案是否适合你。 记住,如果你反对一种方法,你应该足够了解它,知道它的所有错误和正确的做法。 无论哪种方式,懒惰和无知只会导致麻烦。 当有疑问时,选择看似保守的选项,而不是简单的选项。 | ||
==设计== | ==设计== | ||
=== 图形用户界面设计 === | === 图形用户界面设计 === | ||
从零开始,可能需要几年时间才能真正完成任何与GUI相关的工作。 | 从零开始,可能需要几年时间才能真正完成任何与GUI相关的工作。 图形用户界面的“外观”是次要的,因为它们会很轻易地来回更改; 真正决定GUI可用性的是 “功能”,而这并没有在绘制出来的图形中表达出来。 如果你的目标是创建更好的外观而不是更好的操作系统,请考虑实现X窗口管理器而不是整个操作系统。 | ||
===人气=== | ===人气=== | ||
第78行: | 第78行: | ||
* 你的操作系统功能不全(命令行界面太少或GUI不好) | * 你的操作系统功能不全(命令行界面太少或GUI不好) | ||
如果能有几个人用你的操作系统,那你就很幸运了。 今天会流行的操作系统能流行的唯一原因是因为它们在几十年前可用,并解决了需求,当时替代方案较少。 | |||
=== 内存使用率=== | === 内存使用率=== | ||
''我想在我的操作系统上使用少于两千字节的空间!'' | ''我想在我的操作系统上使用少于两千字节的空间!'' | ||
抱歉,那恐怕是不可能的。 使用如此少内存的操作系统几乎无法使用。 忘掉文件系统驱动程序、磁盘驱动程序、USB驱动程序等吧。 | 抱歉,那恐怕是不可能的。 使用如此少内存的操作系统几乎无法使用。 忘掉文件系统驱动程序、磁盘驱动程序、USB驱动程序等吧。 如果你想开发一些小的东西,只需做一个简单的bootloader,而不是操作系统。 | ||
你可以试试原生Forth(译者注:搜索结果,一个60年代开始的计算机解译程序,常用于天文);它就像一个小操作系统,内核、命令解释器和汇编程序都在一个微小的二进制文件中! 内核的某些部分甚至可以编写脚本。 | 你可以试试原生Forth(译者注:搜索结果,一个60年代开始的计算机解译程序,常用于天文);它就像一个小操作系统,内核、命令解释器和汇编程序都在一个微小的二进制文件中! 内核的某些部分甚至可以编写脚本。 你甚至不需要文件系统,许多Forth使用者会直接编辑和加载磁盘扇区。 有一个大问题: Forth的技术并不轻量级。 写好Forth完全是另一个星球,你需要深入了解它。 令人惊讶的是,一些Forth粉丝擅长编写Forth解释器,但却不是很好的Forth程序员。 你需要成为一名优秀的Forth程序员,才能将OS设计概念与Forth相匹配,或者找出哪些概念是不需要的。 如果你无法做到这一点,那么你的操作系统将比Forth所需 “大得多”。;)(哈哈) | ||
找出减少代码大小的方法可能需要很多时间和思考。 Forth的发明者查尔斯·摩尔(Charles Moore)写了一个只有5行代码的CAD程序。 当被问及写这5行花了多长时间时,他回答: “哦,大约2年”! | 找出减少代码大小的方法可能需要很多时间和思考。 Forth的发明者查尔斯·摩尔(Charles Moore)写了一个只有5行代码的CAD程序。 当被问及写这5行花了多长时间时,他回答: “哦,大约2年”! | ||
第92行: | 第92行: | ||
''我的操作系统将能够运行来自Windows、Mac OS、Linux的程序,甚至可以运行PDP-11程序!'' | ''我的操作系统将能够运行来自Windows、Mac OS、Linux的程序,甚至可以运行PDP-11程序!'' | ||
很抱歉打破了你的幻想,但这可能做不到。 即使只模拟一个系统也需要多年的工作,尤其是当它是专有的,比如Windows或Mac OS(Linux可能是四个系统中最简单的一个)。 [http://www.winehq.org/ Wine] | 很抱歉打破了你的幻想,但这可能做不到。 即使只模拟一个系统也需要多年的工作,尤其是当它是专有的,比如Windows或Mac OS(Linux可能是四个系统中最简单的一个)。 [http://www.winehq.org/ Wine],尽管自1993年以来一直在开发,并且是在用户空间中编写的,但许多Windows程序在上面运行仍然存在问题。 | ||
因此,与其专注于模仿其它系统,不如专注于自己的系统。设计它,开发它,并与它成为朋友。 | |||
===编程语言=== | ===编程语言=== | ||
有些语言非常适合编写内核,而其它语言则不太适合。阅读有关[[Languages|C等其它语言]]的页面。 | |||
== 内核映像 == | == 内核映像 == | ||
=== | === 引导错误问题 === | ||
特别是在初步使用自建的Bootloader时,引导错误问题的原因往往是从磁盘获取的扇区太少。 调整从磁盘获取的扇区数量,或者考虑让boot loader/second stage loader解析文件系统。 | |||
<!-- 待办事项: 嗯,这似乎不适合本教程,而且有些过时,因为我们总是推荐使用交叉编译器。 我现在就评论一下。-~~~~ | <!-- 待办事项: 嗯,这似乎不适合本教程,而且有些过时,因为我们总是推荐使用交叉编译器。 我现在就评论一下。-~~~~ | ||
=== 字符串=== | === 字符串=== | ||
当你的内核用C语言编写时,GCC会将字符串和常量放在一个称为“只读数据”的特殊部分中。 这个部分需要在你的链接器脚本中明确添加,否则它会导致各种奇怪的问题 (无法将文本打印到屏幕上,内核突然变大1MB,GRUB给出加载错误,说 “内核太大了”,等等)。 该节在[[ELF]]中名为''.rodata'',在COFF/PE(MinGW/Cygwin的输出格式)中称为''.rdata''。 构建[[GCC Cross-Compiler]]将帮助你安全地处理可能到处都是的“.rodata”。 | 当你的内核用C语言编写时,GCC会将字符串和常量放在一个称为“只读数据”的特殊部分中。 这个部分需要在你的链接器脚本中明确添加,否则它会导致各种奇怪的问题 (无法将文本打印到屏幕上,内核突然变大1MB,GRUB给出加载错误,说 “内核太大了”,等等)。 该节在[[ELF]]中名为''.rodata'',在COFF/PE(MinGW/Cygwin的输出格式)中称为''.rdata''。 构建[[GCC Cross-Compiler]]将帮助你安全地处理可能到处都是的“.rodata”。 | ||
你还可以调整你的链接器脚本以包括 | 你还可以调整你的链接器脚本以包括 “其它” 部分: | ||
<source lang="c"> | <source lang="c"> | ||
第120行: | 第120行: | ||
== 故障排除/请求帮助 == | == 故障排除/请求帮助 == | ||
在论坛或IRC上寻求帮助之前,你应该采取所有可能的步骤自己诊断问题的性质。 在三重故障或“随机”异常等问题的情况下,对问题的原因进行假设是常见的错误。 | 在论坛或IRC上寻求帮助之前,你应该采取所有可能的步骤自己诊断问题的性质。 在三重故障或“随机”异常等问题的情况下,对问题的原因进行假设是常见的错误。 请使用调试器或打印语句来定位异常发生时的确切位置。 使用仿真器和调试器 (如GDB和Bochs/QEMU) 将帮助你找到难以跟踪的问题。 如果你提供一些关于问题的理论和你已经采取的解决措施,人们将能够更容易地帮助你(即使你的理论不正确,它至少会让人们了解你对问题的看法、你可能已经尝试过的策略,以及你可能错过的东西)。 | ||
一般来说,在向别人寻求帮助之前,自己应尽可能多地投入工作来解决问题。 在你发帖之前,问问自己,“我已经尽我所能诊断和解决这个问题了吗?” 通常情况下,你会在这个过程中学到很多东西,你很可能能够自己解决问题(以及将来类似的问题),而不需要别人的帮助,这是一件好事。 当你请求帮助时,请提供与你的问题'''相关'''的代码。 | 一般来说,在向别人寻求帮助之前,自己应尽可能多地投入工作来解决问题。 在你发帖之前,问问自己,“我已经尽我所能诊断和解决这个问题了吗?” 通常情况下,你会在这个过程中学到很多东西,你很可能能够自己解决问题(以及将来类似的问题),而不需要别人的帮助,这是一件好事。 当你请求帮助时,请提供与你的问题'''相关'''的代码。 然而,问题可能位于其它地方,所以可以给别人一种方法来看看你的代码的其它部分。 (如果你使用的工具像GitHub或Bitbucket,会稍微容易一点,但肯定有很多其他的方式)。 | ||
关于论坛,请阅读论坛规则。 | 关于论坛,请阅读论坛规则。 它们是必读的''',这将提高你的帖子的质量,并使人们更有可能帮助你。 在IRC频道上,如果你提出问题,请不要期望在10秒甚至5分钟内得到答案。 其他人也有自己的生活。 如果你需要离开去做某事,并且想检查你是否遗漏了什么,有一些日志可供你查看。 请查看那些IRC专题的链接。 | ||
要想获得关于如何在寻求帮助时成为一名优秀社区成员的更深入指南,请参考[http://www.catb.org/~esr/faqs/smart-questions.html 如何提问]。 这是一本很棒的书,理想情况下,你应该先读完整本书,然后再向任何地方寻求帮助(这本书不是很长,很值得一读)。 | |||
== 升级 == | == 升级 == | ||
第132行: | 第132行: | ||
命名通常是最后一个要解决的问题,即使我们都希望我们的酷概念有一个很酷的名字。 由于名字的 “酷” 是一个品味问题,这我们无法帮助你。 此外,如果你把你的项目名称和某个特性联系在一起,你可能会在未来的某个地方发现,没有一个概念是完美的,你会想改变你最初认为是关键特性的东西。 没有什么比仅仅因为你“想要固守一个名字”而不进化更愚蠢的了…… | 命名通常是最后一个要解决的问题,即使我们都希望我们的酷概念有一个很酷的名字。 由于名字的 “酷” 是一个品味问题,这我们无法帮助你。 此外,如果你把你的项目名称和某个特性联系在一起,你可能会在未来的某个地方发现,没有一个概念是完美的,你会想改变你最初认为是关键特性的东西。 没有什么比仅仅因为你“想要固守一个名字”而不进化更愚蠢的了…… | ||
在 [[Topic:15250|此]]主题中可以找到许多有关命名的良好信息。 简单地说,在你找到第二个项目成员之前,给你的操作系统命名<name>OS(JackOS、FredOS等)似乎是个好主意。 一个好主意(由Solar提供)是选择一个代号( | 在 [[Topic:15250|此]]主题中可以找到许多有关命名的良好信息。 简单地说,在你找到第二个项目成员之前,给你的操作系统命名<name>OS(JackOS、FredOS等)似乎是个好主意。 一个好主意(由Solar提供)是选择一个代号(如Longhorn、Chicago等)。然后在离发行时间更近的时候编一个更好的名字。 | ||
=== 项目网站 === | === 项目网站 === | ||
许多osdev新手在网站上没有任何值得展示的内容之前就创建了项目网站。 在你还不知道项目的发展方向,或者没有任何代码、屏幕截图或下载来展示你已经产生的成果之前,创建一个网站,对你的项目的未来计划做出戏剧性的声明是没有价值的。 这样的网站看起来已经死了,而且造成了不好的名声。 宣布你的网站(比如在OSDev.org论坛上的公告论坛中),或者在你的签名中链接到它,而上面只有一条“欢迎来到<花哨的项目名称> | 许多osdev新手在网站上没有任何值得展示的内容之前就创建了项目网站。 在你还不知道项目的发展方向,或者没有任何代码、屏幕截图或下载来展示你已经产生的成果之前,创建一个网站,对你的项目的未来计划做出戏剧性的声明是没有价值的。 这样的网站看起来已经死了,而且造成了不好的名声。 宣布你的网站(比如在OSDev.org论坛上的公告论坛中),或者在你的签名中链接到它,而上面只有一条“欢迎来到<花哨的项目名称>”的消息,这只会让人们在你还没开始之前就对你的项目失去兴趣,也许当你最终做出值得炫耀的东西时,你将面临一个已经很糟糕的名声,很难克服。 | ||
== 团队合作 == | == 团队合作 == | ||
第151行: | 第151行: | ||
# 如果你名不副实,尤其对那些更有经验的人,他们会对你非常警惕,缺乏加入的信任。 | # 如果你名不副实,尤其对那些更有经验的人,他们会对你非常警惕,缺乏加入的信任。 | ||
# 如果你没有项目管理技能,少数几个“愿意”加入的人很快就会退出,因为他们忙于讨论事情,没有开始编写代码。 | # 如果你没有项目管理技能,少数几个“愿意”加入的人很快就会退出,因为他们忙于讨论事情,没有开始编写代码。 | ||
而随便加入的人员通常比这里提到的程序员能力更差。 | |||
[[Category:OS Development]] | [[Category:OS Development]] |
2022年2月12日 (六) 15:20的最新版本
“编写自己的操作系统”的想法把你带到了这里。 本维基网站希望能在你的工作中给你帮助、指点和参考。
但是,新来者对主题涉及的内容犯某些错误或有共同的误解是很常见的。 这并不是坏事 —— 许多人以前犯过同样的起步错误,将来也会犯。 本文章正是为了确保你在深入学习本维基网站所提供的信息之前理解自己要做的事情。
这不是什么
本网站可能看起来像是一套可以复制和粘贴的教程,再加上一个论坛,同时在你遇到困难时可以在这里问问题。 不是这样的。我们希望你在开始编写自己的操作系统之前有所准备,并成为一名经验丰富的用户空间应用程序程序员。 我们还希望你已经阅读了有关操作系统设计的信息,并且你已经研究了所选平台的相关文档。 不要指望这个维基或论坛是某种“开发自己操作系统的完整指南”,更别说是编程技巧的一般指南了。
你在这里找到的是在你之前的人留下的文档,他们通过阅读技术文档、可用的源代码、论坛帖子以及试错编程发现了这些记录下来的事情。 其中一些是为了让那些人以后可以再次查找它,其中一些是为了让我们可以索引一篇维基文章,而不是 “再次” 解释一个主题。
你在这里可以找到的是一些可能会帮助你走上正确道路的小提示和路标,相反本网站不是一张完整的“绿野仙踪”地图,也不应该是。
如果你还不清楚什么是栈,或者不知道如何使用调试器,我们也不会不厌其烦地向你解释。 访问这上面两个词条链接; 你会看到它们主要涉及操作系统的细节,而不是对该主题的一般介绍。 这不是本网站的遗漏,这是故意的。 如果你正在寻找一般的编程启蒙,你应该先访问像StackOverflow这样的一般编程网站,在立志成为一名“OS”开发人员之前,先成为一名普通软件开发人员。
这个维基将不会扩充成初学者手册,因为那不是它的目的。 它是以回答当人们觉得他们已经准备好投入内核空间编程时出现的高级问题为目标的。
一个残酷的真相
就算拥有多年在各种语言和环境中开发丰富经验的开发人员,在做操作系统开发前仍需要三思。 十多年的编程,包括几年汇编语言和/或系统语言(如C)的低级编码,才是理解操作系统开发的最低要求
更重要的是,随着不同的“标准”、计算机和移动设备型号、外围设备和设计概念的数量不断扩大,开发操作系统的背景门槛越来越高。
对于像丹尼斯·里奇(Dennis Ritchie)、理查德·格林布拉特(Richard Greenblatt)、加里·基尔德尔(Gary Kildall)或史蒂夫·沃兹尼亚克(Steve Wozniak)这样的早期伟人来说,为硬件编写一个简单的操作系统是另一回事。那时他们已经非常了解当时的机器,操作系统相对简单,并且没有标准规范要遵守,也没有旧标准规范需要来保持向后兼容性。 这在当前一代新老硬件上已不再适用。 此外,他们每个人都已经是一名经验丰富的工程师,已经做了多年的系统编程。 即使在那个时代,它们也只是为系统提供了基础结构; 在系统的核心 (用现代行话来说是内核) 到位之后,大部分工作是由一批后续开发人员完成的。
这个现象可能也有例外,但并不多;不要指望自己就是那个千里挑一的人。 如果你认为你是,请阅读邓宁-克鲁格效应,再重新考虑这件事。
哦,郑重声明,Linus Torvalds也并不是万众无一的天才 -- 他在编写linux内核时是一名研究生,并且已经使用C进行了多年编码。 虽然他离十几年的标准还差得很远,但作为一名研究生,他把自己的爱好变成了他的硕士论文,他比大多数人投入更多的时间从事这个项目。 不管怎么说,他在1991年向USENET发布著名的“Linux0.0.1”版本只不过是一个循环调度程序,远远谈不上是一个完整的系统。 而达到这一点花了他一年的时间。 明白了吗?
虽然这个维基的大多数贡献者确实很早就开始尝试操作系统开发了,但对我们大多数人来说,这是一个由于缺乏经验而产生的错误。 这个小组的大多数先驱者甚至不知道一个小型OS项目的规模和复杂性,也不知道他们正在进入什么领域。 这是一个难以下咽的苦药,尤其是在像这个维基这样的资源被广泛使用以前。 我们不能强迫你们从我们的错误中吸取教训,但至少我们可以传递这个警告。
到这里还是希望你不应该对此感到 “太” 气馁; 关键并不在于恐怕你永远做不到,而是你可能 “暂时” 还做不到(我们大多数人开始的时候都是这样)。 在开始这么大的项目时,耐心是一种美德。
是否有关于...的教程?
因为这个地方不能也不适合初学者开发人员,所以经常会有人问起:在其它地方是否有提供更好的解释或易于理解的教程读物。 然而,它们不存在。 困难的学科不能用轻松的散文来描述,就像世上很多东西太复杂了,作为猴子是无法成功学会的一样。 如果你在阅读官方文档时遇到问题,那么这恰恰是练习的好时机。
事实上,目前绝大多数的教程都存在一点两点的问题,所以你最好不要一开始就相信它们。
范围控制
截止边界
无论是大学、业余爱好还是商业用途,操作系统开发都需要时间。 Linux内核花了一年多的时间才显露出用武之地,而Linus Torvalds所做的一切就是“模仿”一些已有且有良好文档说明的设计,而让一个已经存在的用户空间在其上运行。 此外,相对于像Linux这样成功的一个项目,实际上同时也有 “数百” 个项目消耗了一年或更长时间,却没有能成功托管一个可用Shell出来。
因此,你需要为你想做的事情规划一个合理的路线图。 不要假设你的操作系统在3个月内就会有GUI和语音识别,因为操作系统开发中根本不包含任何RAD(快速应用开发)工具。 实际上,RAD对操作系统开发是void。 ('void. 这是个笑话。 你Get到了吗?)
最终目标定义
在开始一个项目时,你应该估计你的最终目标、你的最终用户、开发该项目的目的等。 操作系统开发与此没有什么不同。 对你的目标有一个大致的了解会给你动力和方向。 然而,当你想到更好的事情时,不要停留在最初的最终目标上。
不幸的是,许多操作系统开发人员没有估计他们的最终操作系统会是什么样子; 因此,他们不知道该朝哪个方向前进,反而向他人求助 “下一步是什么?”
应该明确的是,为了估计最终目标,你应该了解现有操作系统如何工作的整个(技术)概念。
商业OSDev
不要以为构建如此出色的操作系统会使你变得富有。 不管怎样,历史已经告诉我们,最好的操作系统永远不会获得任何商业成功,而那些几乎完全缺乏设计和灵感的操作系统却获得了商业成功,因为它们有着巧妙的商业小动作,在正确的时间,在正确的地点,进行正确的缺点掩盖。
尽管如此,尽管论坛的“乔布斯”部分相对空洞,但一些独家开发的操作系统已经取得了一些商业上的成功。 一个例子是 01000101,它具有 “接入网络安全”特性,一种被设计为充当专用深度包分析器的OS。 请注意,它专门用于特定的应用程序。 要以这种方式推销你的操作系统,你需要像了解OS开发人员一样了解应用程序,甚至更好,而且你需要对这两种情况都非常擅长编码。 你的客户会期望你是专业的。
另一种可能性是向目前还使用MS-DOS进行工作控制的公司销售操作系统。 这看起来可能更简单,因为你不负责最终的应用程序,但你需要专业并对客户的问题和查询做出响应。 他们可能需要长期支持。 他们可能不喜欢你真正想要实现的功能。
假设它不会有任何结果
与上述相反,有些人认为他们的操作系统将毫无用处。 由于这个原因,他们的项目有丑陋的代码,重要的方面不考虑,通常依赖丑陋的黑客式技巧。 最糟糕的是,他们做出的决策不会带来可用性和可扩展性。 这样,他们的假设就变成了一个自我实现的预言。
实际上,虽然让操作系统在测试机器之外运行的可能性很低,但从这个社区开始的高级操作系统项目有很多了。
避免无知
初学者经常问 “做X的“ 最容易 ”的方法是什么?” 而不是 “做X的最佳,适当,正确的方法是什么?” 这是危险的,因为新手不会花时间去理解实现某个东西的更好方法,而是从教程中选择概念上更简单的方法。 事实上,更简单的路线往往“太简单”,从长远来看,最终会造成更多问题,因为初学者对更好的替代方案一无所知,也不知道什么时候换更好。 走难走的路又有什么不好?
常见的例子包括懒得使用交叉编译器,不理解实模式、非实模式、保护模式,以及Long Mode,从一个点到另一个点跳得太快,而没有首先了解如何收集所有重要配置并充分利用其所有功能(尤其是在引导和初始化期间使用BIOS检测基本功能),依赖于非标准的BIOS调用,不学习在自己的操作系统以及Windows和Linux下编写硬件驱动程序以获得最大的便利,在全球范围内公开测试功能,使用简单二进制文件而不是ELF,不学习可执行文件、归档文件、图形、文档和其它文件格式以及压缩算法,等等。 有经验的开发人员使用更好的替代方案是有原因的,你可能还不明白这一点。 经验丰富的开发人员在某些情况下选择使用劣质方法,但这是因为他们可以仔细分析它是否合适,并且知道何时 “不” 使用它。 作为一名初学者或中级开发人员,你可能不太了解这些方法和技术,无法判断劣质解决方案是否适合你。 记住,如果你反对一种方法,你应该足够了解它,知道它的所有错误和正确的做法。 无论哪种方式,懒惰和无知只会导致麻烦。 当有疑问时,选择看似保守的选项,而不是简单的选项。
设计
图形用户界面设计
从零开始,可能需要几年时间才能真正完成任何与GUI相关的工作。 图形用户界面的“外观”是次要的,因为它们会很轻易地来回更改; 真正决定GUI可用性的是 “功能”,而这并没有在绘制出来的图形中表达出来。 如果你的目标是创建更好的外观而不是更好的操作系统,请考虑实现X窗口管理器而不是整个操作系统。
人气
“我的操作系统将比Windows,Mac操作系统和Linux更受欢迎!”
这是极不可能的。 要做到这一点,需要相当多的时间、金钱和知识。 不是每个人都会下载你的操作系统,因为:
- 他们可能不知道什么是操作系统,也不知道如何安装操作系统
- 你的操作系统存在安全风险
- 你的操作系统支持更少的应用程序
- 你的操作系统功能不全(命令行界面太少或GUI不好)
如果能有几个人用你的操作系统,那你就很幸运了。 今天会流行的操作系统能流行的唯一原因是因为它们在几十年前可用,并解决了需求,当时替代方案较少。
内存使用率
我想在我的操作系统上使用少于两千字节的空间!
抱歉,那恐怕是不可能的。 使用如此少内存的操作系统几乎无法使用。 忘掉文件系统驱动程序、磁盘驱动程序、USB驱动程序等吧。 如果你想开发一些小的东西,只需做一个简单的bootloader,而不是操作系统。
你可以试试原生Forth(译者注:搜索结果,一个60年代开始的计算机解译程序,常用于天文);它就像一个小操作系统,内核、命令解释器和汇编程序都在一个微小的二进制文件中! 内核的某些部分甚至可以编写脚本。 你甚至不需要文件系统,许多Forth使用者会直接编辑和加载磁盘扇区。 有一个大问题: Forth的技术并不轻量级。 写好Forth完全是另一个星球,你需要深入了解它。 令人惊讶的是,一些Forth粉丝擅长编写Forth解释器,但却不是很好的Forth程序员。 你需要成为一名优秀的Forth程序员,才能将OS设计概念与Forth相匹配,或者找出哪些概念是不需要的。 如果你无法做到这一点,那么你的操作系统将比Forth所需 “大得多”。;)(哈哈)
找出减少代码大小的方法可能需要很多时间和思考。 Forth的发明者查尔斯·摩尔(Charles Moore)写了一个只有5行代码的CAD程序。 当被问及写这5行花了多长时间时,他回答: “哦,大约2年”!
操作系统仿真
我的操作系统将能够运行来自Windows、Mac OS、Linux的程序,甚至可以运行PDP-11程序!
很抱歉打破了你的幻想,但这可能做不到。 即使只模拟一个系统也需要多年的工作,尤其是当它是专有的,比如Windows或Mac OS(Linux可能是四个系统中最简单的一个)。 Wine,尽管自1993年以来一直在开发,并且是在用户空间中编写的,但许多Windows程序在上面运行仍然存在问题。
因此,与其专注于模仿其它系统,不如专注于自己的系统。设计它,开发它,并与它成为朋友。
编程语言
有些语言非常适合编写内核,而其它语言则不太适合。阅读有关C等其它语言的页面。
内核映像
引导错误问题
特别是在初步使用自建的Bootloader时,引导错误问题的原因往往是从磁盘获取的扇区太少。 调整从磁盘获取的扇区数量,或者考虑让boot loader/second stage loader解析文件系统。
故障排除/请求帮助
在论坛或IRC上寻求帮助之前,你应该采取所有可能的步骤自己诊断问题的性质。 在三重故障或“随机”异常等问题的情况下,对问题的原因进行假设是常见的错误。 请使用调试器或打印语句来定位异常发生时的确切位置。 使用仿真器和调试器 (如GDB和Bochs/QEMU) 将帮助你找到难以跟踪的问题。 如果你提供一些关于问题的理论和你已经采取的解决措施,人们将能够更容易地帮助你(即使你的理论不正确,它至少会让人们了解你对问题的看法、你可能已经尝试过的策略,以及你可能错过的东西)。
一般来说,在向别人寻求帮助之前,自己应尽可能多地投入工作来解决问题。 在你发帖之前,问问自己,“我已经尽我所能诊断和解决这个问题了吗?” 通常情况下,你会在这个过程中学到很多东西,你很可能能够自己解决问题(以及将来类似的问题),而不需要别人的帮助,这是一件好事。 当你请求帮助时,请提供与你的问题相关的代码。 然而,问题可能位于其它地方,所以可以给别人一种方法来看看你的代码的其它部分。 (如果你使用的工具像GitHub或Bitbucket,会稍微容易一点,但肯定有很多其他的方式)。
关于论坛,请阅读论坛规则。 它们是必读的,这将提高你的帖子的质量,并使人们更有可能帮助你。 在IRC频道上,如果你提出问题,请不要期望在10秒甚至5分钟内得到答案。 其他人也有自己的生活。 如果你需要离开去做某事,并且想检查你是否遗漏了什么,有一些日志可供你查看。 请查看那些IRC专题的链接。
要想获得关于如何在寻求帮助时成为一名优秀社区成员的更深入指南,请参考如何提问。 这是一本很棒的书,理想情况下,你应该先读完整本书,然后再向任何地方寻求帮助(这本书不是很长,很值得一读)。
升级
命名
命名通常是最后一个要解决的问题,即使我们都希望我们的酷概念有一个很酷的名字。 由于名字的 “酷” 是一个品味问题,这我们无法帮助你。 此外,如果你把你的项目名称和某个特性联系在一起,你可能会在未来的某个地方发现,没有一个概念是完美的,你会想改变你最初认为是关键特性的东西。 没有什么比仅仅因为你“想要固守一个名字”而不进化更愚蠢的了……
在 此主题中可以找到许多有关命名的良好信息。 简单地说,在你找到第二个项目成员之前,给你的操作系统命名<name>OS(JackOS、FredOS等)似乎是个好主意。 一个好主意(由Solar提供)是选择一个代号(如Longhorn、Chicago等)。然后在离发行时间更近的时候编一个更好的名字。
项目网站
许多osdev新手在网站上没有任何值得展示的内容之前就创建了项目网站。 在你还不知道项目的发展方向,或者没有任何代码、屏幕截图或下载来展示你已经产生的成果之前,创建一个网站,对你的项目的未来计划做出戏剧性的声明是没有价值的。 这样的网站看起来已经死了,而且造成了不好的名声。 宣布你的网站(比如在OSDev.org论坛上的公告论坛中),或者在你的签名中链接到它,而上面只有一条“欢迎来到<花哨的项目名称>”的消息,这只会让人们在你还没开始之前就对你的项目失去兴趣,也许当你最终做出值得炫耀的东西时,你将面临一个已经很糟糕的名声,很难克服。
团队合作
合作问题是在公告论坛中可以看到的最多的初学者错误。 它通常以两种形式之一出现,尽管两种形式有相当多的重叠:
社区项目
不要高估人们对 “你的” 项目参与的兴趣。 即使是那些更成功的项目通常也由一个或两个实际从事代码工作的人组成。 这并不是因为项目“不需要”。
布鲁克斯定律指出,项目上的人越多,项目花费的时间就越长。 解决这个问题的唯一方法是将项目分成几个部分,让人们参与其中,并且只参与部分。 祝好运。
招聘
你需要一些东西来获得人们加入项目(避免痛苦地被告知你是个失败者):
- 如果你没有既定的代码库,人们不会加入,因为他们看到你缺乏经验,预计项目会失败。
- 如果你缺乏 (有效的) 设计,人们将不会加入你的行列,因为他们看不到你的操作系统比他们自己的设计更有趣。
- 如果你名不副实,尤其对那些更有经验的人,他们会对你非常警惕,缺乏加入的信任。
- 如果你没有项目管理技能,少数几个“愿意”加入的人很快就会退出,因为他们忙于讨论事情,没有开始编写代码。
而随便加入的人员通常比这里提到的程序员能力更差。