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

将 Go 程序跑在裸机上之 LibOS

  •  3
     
  •   icexin · 331 天前 · 2980 次点击
    这是一个创建于 331 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    之前我写过一篇探索在裸机上运行 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/[email protected] 得到。

    我们的例子都是在 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  
       331 天前
    炫确实是挺炫。
    不过操作系统最大的意义是提供硬件资源的调度,libos 感觉太偏向底层了,损失了很多便利性。
    yanzhiling2001
        2
    yanzhiling2001  
       331 天前
    6B
    lesismal
        3
    lesismal  
       331 天前
    虽然自己用不上,但是很喜欢这感觉,已 star 。
    wangyu17455
        4
    wangyu17455  
       331 天前
    酷啊
    kwanzaa
        5
    kwanzaa  
       331 天前
    要是能作为 VPS 的镜像,多棒。
    icexin
        6
    icexin  
    OP
       331 天前
    @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
       331 天前
    @Actrace 感谢关注,目前作为实验性项目,并不具有生产可用性哈。不过业界的确有 unikernel 的研究方向,在嵌入式和云环境还是有一定的使用场景。
    ipwx
        8
    ipwx  
       331 天前
    @icexin 个人觉得:

    嵌入式:行
    云环境:不行

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

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

    如果跑在树莓派之类的大内存开发板,感觉浪费了硬件。但是如果能跑在树莓派 pico 、ESP8266 、ESP32 、荔枝派 Nano 之类的迷你硬件上,应该会很好玩。
    wupeaking
        15
    wupeaking  
       330 天前
    期待能支持嵌入式的开发, 毕竟通用的 X86 架构不跑操作系统没事意义呀。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1119 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 21:54 · PVG 05:54 · LAX 14:54 · JFK 17:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.