Golang Go语言中编写的跑在x86裸机上的unikernel

发布于 1周前 作者 wuwangju 来自 Go语言

Golang Go语言中编写的跑在x86裸机上的unikernel

github 地址 https://github.com/icexin/eggos

这是一个使用 Go 编写的运行于 x86 机器的 unikernel,全部用 go 编写(除了 bootloader 和一些汇编)

Go 的 runtime 提供了一些基本的操作系统抽象,goroutine 对应进程,channel 对应进程间通信,另外 go 有自己的虚拟内存管理,所以萌生了在裸机上运行 Go 程序的想法。

实际证明,Go 有操作硬件资源的能力,得益于 Go 可控的内存布局,以及不需要虚拟机直接翻译硬件指令的能力,还有类 C 的语法。这些都让 Go 编写运行于裸机的程序有了可能。

然而也有一些挑战,Go 在很多指令里面打桩来进行协程调度以及内存 GC,在一些不能重入的地方,如中断处理和系统调用,都带来了一些麻烦。

功能 list

  • 基本的 go 功能,goroutine,channel,GC 等
  • 大部分标准库
  • TCP/IP 网络栈
  • VFS 抽象
  • nes 模拟器,js 解释器等

一些快照

支持 http get 的 js 解释器

js

nes 模拟器

nes

欢迎学习交流!


更多关于Golang Go语言中编写的跑在x86裸机上的unikernel的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

23 回复

厉害了,已点 star
未来会支持 x86_64 和 uefi 吗,毕竟现在也没有多少 x86 的机器了

更多关于Golang Go语言中编写的跑在x86裸机上的unikernel的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


x86_64 在计划中,切换到 64 位应该还好,主要是分页管理以及一些系统调用的不一样,可能有一些其他的坑,使用 multiboot 作为 bootloader 主要是方便 qemu 调试。

学习了,厉害

可执行文件是 elf 格式的吗,标准库是 c 库吗?

这是一个单应用的内核,整个内核是一个 go 程序,暂不支持运行多进程,但是可以运行多个 goroutine 。内核的格式是 elf,标准库是指 go 的标准库。

厉害,Star 了。加油。

我用 cxx 写过 os 但没想到还有这么屌的

这脑洞,好牛逼……还能跑起来了……

楼主是实现了 go runtime 吗,可以运行 elf 也可以运行 go 程序?看介绍是实现了大部分 go 标准库?这就很强大了。

Unikernel 的意思就是程序作为代码连接进内核中,所以没有 elf 加载器之类的.

[email protected]/sleep/commit_noasm.go:38:45: undefined: preparingG 编译失败 😂

rust 更适合干这活啊

> Go 在很多指令里面打桩来进行协程调度以及内存 GC

这里的打桩具体指的是?

Go 的编译器会在函数入口检查栈是否溢出,如果溢出就执行 runtime 函数扩容,可能会触发调度,还有一些 writeBarrier 用于辅助 GC

现在只支持 go1.13 哈,其他版本可能会出现问题

感谢解答,用汇编写过玩具内核,第一次接触 unikernel

我记得 go 设计出来的时候,为了显示 自举 和 兼容性,设计团队就在裸机上跑过

是用什么来模拟 x86 裸机呢

开发的时候用的 qemu,最终用 grub 引导在我自己的台式机上跑

虽然现在的 cpu 都是 64 位的,但如果没有显式开启 64 位,是可以运行于传统的 32 位保护模式下的。

在Golang中编写运行在x86裸机上的unikernel是一个高级且富有挑战性的任务,这通常涉及到底层系统编程和操作系统原理的深入理解。以下是一些关键点和建议:

  1. 了解裸机环境

    • 裸机(bare-metal)意味着没有操作系统层的抽象,你的代码直接与硬件交互。
    • 熟悉x86架构的启动过程(如BIOS/UEFI引导),以及内存映射、中断和I/O端口等硬件资源。
  2. 使用适当的工具链

    • 使用像x86_64-elf-gcc这样的交叉编译器来编译你的Golang代码为目标架构。
    • 可能需要自定义的链接脚本和启动代码(如用汇编语言编写的启动器)。
  3. 管理内存和中断

    • 在没有操作系统支持的情况下,手动管理内存分配和释放。
    • 设置并处理中断,特别是与硬件交互时必不可少的定时器中断和I/O中断。
  4. 编写简单的操作系统框架

    • 使用Golang编写基本的操作系统服务,如任务调度、内存管理、文件系统抽象(如果需要)等。
    • 由于Golang的runtime依赖于操作系统提供的服务,你可能需要实现或绕过这些依赖。
  5. 测试和调试

    • 使用硬件模拟器(如QEMU)进行初步测试,以避免直接在物理硬件上运行可能导致的损坏。
    • 利用串行端口或其他调试接口进行日志记录和调试。

编写unikernel是一个复杂的项目,建议从简单的操作系统原理开始,逐步增加复杂性。

回到顶部