为什么不能用 Go 开发操作系统?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

高级前端进阶

本篇文章是译文,来自 Sergey Kozlovskiy 在 2023 年 5 月 16 日发布的文章《OS in Go? Why Not?》。因为我对这个话题也比较感兴趣,所以特地翻译过来给大家阅读,原文链接在文末已经给出。

前言

操作系统是计算机系统的心脏和灵魂。 操作系统管理计算机的硬件和软件资源,并为用户提供与计算机交互的方式。 传统意义上,C 和 Assembly 等语言因其低开销和“接近机器”的特性而被用于编写操作系统。 但是 Go 等高级语言的兴起引入了一些功能,这些功能应该可以使开发操作系统等复杂软件变得更加容易。 例如,类型安全、错误处理和并发性等特性在编写操作系统时可能是有利的。 这些特性表明,像 Go 这样的高级语言将是操作系统开发的自然选择。 那么,为什么 Go 到目前为止还没有涉及操作系统研发领域呢?

Go 语言与操作系统

本文将带你了解为什么像 C 这样的语言在 OS 开发中占据优势,以及是否可以使用 Go 编写 OS。

1.为什么操作系统或内核是用 C 和汇编语言编写

确定使用哪种语言编写特定操作系统可能具有挑战性,因为每个操作系统都是用多种语言的组合编写的。

操作系统由具有不同职责的不同组件组成,可以用不同的语言编写。

本文明确关注 Go 是否适合编写操作系统内核。如前面所说的,几乎所有的主要内核都是用 C 编写的,当然也有一些汇编。 C 统治内核的世界主要有以下几个原因:

但是,C 本身通常不足以编写整个内核,因此在某些情况下开发者需要编写汇编代码:

2.为什么 Go 可以成为操作系统开发的替代语言

像 Go 这样的高级语言确实提供了一些优秀的特性,从表面上看似乎是操作系统开发的绝佳选择:

某些类型的错误在高级语言中出现的可能性要小得多,比如:缓冲区溢出和释放后使用错误在 Go 等语言中几乎是不可能的。同比之下,即使是专业开发者非常仔细地编写的 C 代码也可能无意中包含这样的错误。

释放后使用错误非常普遍,以至于 Linux 内核包含一个内存检查器,用于在运行时检测一些释放后使用和缓冲区溢出错误。同时,在高级语言中处理并发更容易,因为几乎每种高级语言都带有处理内置并发所需的机制。像 Go 这样的语言的类型安全可以防止 C 的宽松类型强制执行。

3.为什么 Go 没有用于 OS/Kernel 开发

尽管 Go 提供了优秀的功能,可以让操作系统开发人员的工作更轻松,但它也有一些局限性。

作为一种具有垃圾回收功能的语言,Go 并不真正适合操作系统开发。 在 Go 中编写内核意味着通过仔细编写代码以最小化堆使用来小心翼翼地绕过 Go 的垃圾收集。 正如此 Reddit 线程中所解释的(参考文献中),鼠标滞后可能是因为中断处理程序分配了触发垃圾回收的内存。

Go 还需要运行时才能执行,这意味着它不能直接在硬件上运行。 尽管 TinyGo 可以将 Go 编译为在裸机上运行,但与 C 相比,它只支持少量的架构,C 几乎可以在任何架构上运行。

另一个相关问题是系统调用构成了典型 Go 运行时中的大量操作。 运行时与操作系统通信以进行各种操作,例如:写入文件或启动线程。 但是,当编写操作系统时,必须在裸机上实现这些操作并破解 Go 运行时以调用实现。 然后问题归结为是否真的想花这么多时间和精力来破解运行时,而其他语言如 C 允许开发者立即开始编写操作系统。

正如您看到的,用 Go 编写操作系统并非不可能。 然而,编写可供一般用户使用的优秀操作系统几乎是不可能的。 编写在单一架构上启动并放入 shell 的操作系统很容易,但是使用 Go 编写一个在多个架构上运行的操作系统,支持不同的设备,如:视频卡或网卡,并且符合 POSIX 标准则非常具有挑战性。

4.用 Go 编写的操作系统

虽然 Go 不是操作系统开发的最合适选择,但这并不意味着用 Go 编写操作系统是不可能的,许多研究项目正在探索如何做到这一点。比如:Biscuit、gopher-os、Clive、gVisor 等等。

Biscuit

Biscuit 是一个用 Go 编写的操作系统,运行在 64 位 X86 架构上。 它使用经过修改的 Go 1.10 运行时实现,其中添加了更多汇编代码来处理系统调用和中断处理程序的引导和进入/退出。 以汇编语言编写的引导块加载 Go 运行时和一个“垫片”层。 Go 运行时期望与底层内核进行各种功能的通信。 由于没有底层内核,“垫片”层提供了这些功能。

Biscuit 为用户进程提供 POSIX 接口,支持 fork、exec 等。它实现了支持核心 POSIX 文件系统调用的文件系统。 Biscuit 为用 Go 编写的 Intel PCI-Express 以太网 NIC 实现了 TCP/IP 堆栈和驱动程序。 使用 POSIX 接口,Biscuit 可以在不修改源代码的情况下运行许多 Linux C 程序。

然而,Biscuit 缺少许多功能,例如:调度优先级、换出页面或磁盘,以及安全功能,例如用户、访问控制列表和地址空间随机化。

gopher-os

gopher-os 是另一个用 Go 编写的概念验证内核。 与 Biscuit 一样,它使用汇编来设置 Go 运行时并加载内核。 然而,它仍处于开发的早期阶段,自 2018 年以来没有收到任何更新,在最新版本的 Go 上也有问题。

Clive 和 gVisor

Clive 是另一个用 Go 编写的 unikernel,但它不在裸机上运行,并且使用经过修改的 Go 编译器来编译 Clive 软件。而 gVisor 是一个用 Go 编写的应用程序内核,它在沙箱容器中实现了 Linux 系统 API。

本文总结

尽管 C 是操作系统开发的主导语言,但 Go 提供了类型安全、自动内存管理和并发等特性,使其有可能成为操作系统开发的绝佳选择。 然而,缺乏对运行时语言不同方面的微调控制,再加上 C 的流行,使得 Go 很难在操作系统开发领域站稳脚跟。

然而,一些研究操作系统已经用 Go 编写,可以期待在不久的将来用 Go 编写对消费者友好的操作系统。

参考资料

原文作者:Sergey Kozlovskiy

原文标题:《OS in Go? Why Not?》

译文作者:头条高级前端进阶

https://www.oschina.net/news/242069/os-in-golang-why-not

https://blog.jetbrains.com/go/2023/05/16/os-in-go-why-not/#OperatingsystemswritteninGo

https://www.reddit.com/r/golang/comments/3im7ps/comment/cuhpq9n/?utm_source=share&utm_medium=web2x&context=3

https://golangdocs.com/golang-os-package

展开阅读全文

页面更新:2024-05-12

标签:进阶   裸机   操作系统   堆栈   开发者   内核   错误   语言   高级   功能

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top