V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
icexin
V2EX  ›  Go 编程语言

将 Go 程序跑在裸机上之 LibOS

  •  3
     
  •   icexin ·
    icexin · 2021-08-08 11:00:44 +08:00 · 3528 次点击
    这是一个创建于 989 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    之前我写过一篇探索在裸机上运行 Go 程序的文章,里面介绍了在裸机上运行 Go 代码需要的技术,顺便介绍了 eggos,一个运行于裸机的 unikernel 。

    在编写eggos的过程中,我发现刨去内核代码,主程序代码其实就是一个普通的 Go 程序,跟其他 Go 程序一样从 main 函数进去,只不过从来不返回。

    那能不能让其他普通程序也运行于裸机呢?因此我把 eggos 的 kernel 抽离出来,作为一个单独的库,其他应用程序只要写下 import _ "github.com/icexin/eggos",即可像 eggos 一样运行在裸机上。

    即使是一个普通的 Go 程序,要在裸机上运行,编译过程还是有很多复杂的参数,因此我把这些编译过程封装了一下,编写了一个叫 egg 的程序,用这个程序来编译,打包,运行你自己编写的 Go 语言编写内核。

    使用 Go 语言编写自己的 unikernel

    eggos 的主仓库里面带了几个示范的例子,在 examples 目录下,下面一一介绍这些例子。

    其中需要注意的是,机器的环境准备如下:

    • Go1.16.x
    • Qemu 模拟器

    egg程序可以从 eggos 的 Release 页面下载,或者运行 go install github.com/icexin/eggos/cmd/egg@latest 得到。

    我们的例子都是在 qemu 模拟器里面运行,如果想在真实的机器上运行这些例子,可以参考动画那个例子,使用 iso 镜像在真机上运行。

    Hello Eggos

    代码在 hello world

    第一个例子比较简单,就是简单输出 hello eggos,用来检查你的环境是否准备完毕

    $ cd helloworld
    $ egg run
    

    Concurrent prime sieve

    代码在 prime sieve

    第二个例子是 Go 官网经典的并发筛选素数的算法,这个例子展示了 eggos 使用 goroutine 的能力。

    $ cd prime-sieve
    $ egg run
    

    HTTP 服务器

    代码在 http server

    第三个例子展示的是 eggos 的网络栈,可以运行 Go 标准库里面的 http

    $ cd httpd
    $ egg run -p 8000:8000
    

    打开浏览器,输入 http://127.0.0.1:8000/hello 即可访问。

    因为我们是在 qemu 里面运行,因此做了端口映射,如果是裸机上运行,把 127.0.0.1替换成机器 IP 即可。

    交互式程序

    代码在 repl

    第四个例子展示了 eggos 的使用输入输出编写交互程序的例子,这个例子通过获取用户输入的字符串,计算其 sha1值,并输出到屏幕。

    $ cd repl
    $ egg run
    

    通过关闭 qemu 的窗口即可关闭程序。

    图形与动画

    代码在 graphic

    第五个例子展示了 eggos 操作图像的能力。Go 的标准库里面的 image 有基础的图形处理能力,eggos 借助 frame buffer,具备基础的处理图像的能力。

    这个例子的代码是从 《 Go 程序设计语言》里面借鉴来的,本来的例子是生成一个 利萨茹曲线 (Lissajous curve) 的 GIF 动图,这里进行少稍微的改造,形成屏幕上的动画。

    这个例子的命令比其他的多一些,之前的例子不牵扯到在屏幕上画图,我们使用 qemu 的 -kernel 参数加载内核即可,在这种模式下,qemu 是不会帮我们找到 frame buffer的。但在这个例子里面我们需要借助 grub 帮我们找到 frame buffer,因此生成了包含 grub 引导程序的 iso 镜像。

    $ cd graphic
    $ egg pack -o graphic.iso
    $ egg run graphic.iso
    

    Hack 系统调用

    代码在 syscall

    eggos 本身只包含了一些基础 Linux 系统调用,来让 Go 的 runtime 能正常运行,但是一些第三方库如果使用了 eggos 没有提供的系统调用可能不可以正常运行,因此 eggos 提供了自助注册系统调用的能力。 这个例子展示了如何自助注册系统调用。

    $ cd syscall
    $ egg run
    

    将内核运行在真机上

    图形与动画 这个例子里面我们展示了如何将内核打包成一个 iso 文件,这个 iso 文件包含了引导程序,因此可以被真机识别并加载运行。

    我们让裸机运行 iso 文件的通常的做法是把 iso 文件烧录到 U 盘或者移动硬盘里面,之后使用 U 盘或者移动硬盘插到电脑上,选择启动项运行。但在这里我推荐使用 ventoy来做启动盘,ventoy 只会格式化 U 盘一次,之后只用拷贝 iso 文件即可,非常方便。这是我在真机上的截图。

    bare-metal

    结语

    借助于 Go 语言的包管理功能,我们成功提供了一个 libos 的 Go 语言实现,让普通 Go 程序也可以跑在裸机上,这是一个非常有趣的尝试,我后面希望硬件驱动之类的也可以模块化,大家在 eggos 这个 unikernel 框架下定制自己的内核像 import 普通 Go package 一样简单!感谢阅读!

    原文地址: https://icexin.com/post/write-your-own-unikernel/

    15 条回复    2021-08-09 11:51:44 +08:00
    Actrace
        1
    Actrace  
       2021-08-08 11:16:46 +08:00
    炫确实是挺炫。
    不过操作系统最大的意义是提供硬件资源的调度,libos 感觉太偏向底层了,损失了很多便利性。
    yanzhiling2001
        2
    yanzhiling2001  
       2021-08-08 11:17:13 +08:00
    6B
    lesismal
        3
    lesismal  
       2021-08-08 12:14:46 +08:00
    虽然自己用不上,但是很喜欢这感觉,已 star 。
    wangyu17455
        4
    wangyu17455  
       2021-08-08 12:32:55 +08:00
    酷啊
    kwanzaa
        5
    kwanzaa  
       2021-08-08 14:21:56 +08:00
    要是能作为 VPS 的镜像,多棒。
    icexin
        6
    icexin  
    OP
       2021-08-08 14:29:16 +08:00
    @kwanzaa 感谢关注,这个是我后续尝试的方向,但目前看来比较比较困难,云厂商都会限制上传自定义镜像的格式,特别是目录结构以及对 cloud-init 的支持,比如阿里云的这个 https://www.alibabacloud.com/help/zh/doc-detail/48226.htm?spm=a2c63.p38356.879954.4.3fa81c9287RlTk#concept-d53-2jm-xdb
    icexin
        7
    icexin  
    OP
       2021-08-08 14:32:17 +08:00
    @Actrace 感谢关注,目前作为实验性项目,并不具有生产可用性哈。不过业界的确有 unikernel 的研究方向,在嵌入式和云环境还是有一定的使用场景。
    ipwx
        8
    ipwx  
       2021-08-08 14:37:13 +08:00
    @icexin 个人觉得:

    嵌入式:行
    云环境:不行

    云环境上哪个项目不是要快速迭代的。一快速迭代连 Go 都只是工具,Python / Go / C++ / Java ; MySQL / Postgres / MongoDB / Redis 哪个好用用哪个。
    kwanzaa
        9
    kwanzaa  
       2021-08-08 17:47:09 +08:00
    @ipwx 专供 Go 的 Serverless 方向我觉得还不错。
    superhack
        10
    superhack  
       2021-08-08 18:37:36 +08:00
    Interesting
    lekai63
        11
    lekai63  
       2021-08-08 19:19:27 +08:00 via iPhone
    serverless 可以
    ipwx
        12
    ipwx  
       2021-08-08 19:42:11 +08:00
    @kwanzaa 没啥用。虚拟机的开销比容器大对不?管理起来也比容器麻烦对不? Kubernetes 容器随便 deploy 它不香嘛。
    ipwx
        13
    ipwx  
       2021-08-08 19:42:53 +08:00
    serverless 说到底也是在某个云平台的 server 上集中灵活调度。less 是针对应用层开发人员的。灵活调度这方面,用 vm 做简直是舍近求远。
    fox0001
        14
    fox0001  
       2021-08-08 20:12:06 +08:00 via Android
    嵌入式确实可行,但是有什么硬件能跑?

    go 能编译 ARM CPU 可执行代码,那么嵌入式硬件是否会限制在 ARM ?

    如果跑在树莓派之类的大内存开发板,感觉浪费了硬件。但是如果能跑在树莓派 pico 、ESP8266 、ESP32 、荔枝派 Nano 之类的迷你硬件上,应该会很好玩。
    wupeaking
        15
    wupeaking  
       2021-08-09 11:51:44 +08:00
    期待能支持嵌入式的开发, 毕竟通用的 X86 架构不跑操作系统没事意义呀。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   995 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:32 · PVG 04:32 · LAX 13:32 · JFK 16:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.