In the process of writing eggos, I found that removing the hardware initialization code, the main program is actually an ordinary Go program. Like other Go programs, the main function is used as the entry point, but it never returns.
Can other ordinary programs also run on bare metal? The answer is yes. I extracted the kernel code of eggos as a separate Go library. Other applications can run on bare metal like eggos by writing
import _ "github.com/icexin/eggos".
If an ordinary Go program wants to run on bare metal, in addition to import eggos, it also needs to pass many complex parameters to the compiler. I encapsulated these compilation processes and wrote a program called
egg. In this way, you can use
egg to compile, package, and run the Go language kernel written by yourself.
Use Go to write your own unikernel
There are several examples in the main code repository of eggos, in the examples directory, the following will introduce these examples one by one.
It should be noted that all examples depend on the following:
- The Qemu emulator
egg program can be downloaded from eggos’s Release page, or run
go install github.com/icexin/eggos/cmd/egg@latest to get it.
Our examples are all running in the qemu emulator. If you want to run these examples on a real machine, you can refer to the
graphic example and use the iso image to run on the real machine.
The code is in hello world
The first example is relatively simple, it simply outputs
hello eggos to check whether your environment is ready.
Concurrent prime sieve
The code is in prime sieve
The second example is the classic algorithm for
Concurrent prime sieve on the Go official website. This example demonstrates the ability of eggos to use goroutines.
The code is in http server
The third example shows the eggos network stack, which can run the
http package in the Go standard library
Open the browser and enter http://127.0.0.1:8000/hello to access.
Because we are running in qemu, port mapping is used. If running on bare metal, just replace
127.0.0.1 with the machine IP.
The code is in repl
The fourth example shows an example of using input and output to write an interactive program. This example obtains the string entered by the user, calculates its sha1 value, and outputs it to the screen.
You can close the program by closing the qemu window.
Graphics and Animation
The code is in graphic
The fifth example demonstrates eggos' ability to manipulate images. The
image package in Go’s standard library has basic graphics processing capabilities, and eggos has basic image processing capabilities with the help of Frame Buffer.
The code of this example is borrowed from the “Go Programming Language”. The original example is to generate a Lissajous curve GIF animation, here is a little modification to form an animation on the screen.
This example has more commands than others. The previous example does not involve drawing pictures on the screen. We can use qemu’s
-kernel parameter to load the kernel. In this mode, qemu will not help us find the
frame buffer. But in this example, we need to use grub to help us find the
frame buffer, so an iso image containing the grub boot program is generated.
Hacking system call
The code is in syscall
Eggos itself only contains some basic Linux system calls to allow Go runtime to run normally, but some third-party libraries may not run normally if they use system calls that are not provided by eggos, so eggos provides the ability to register system calls. This example shows how to register system calls.
Run the kernel on the real machine
In the example of
Graphics and Animation, we showed how to package the kernel into an ISO file. This ISO file contains the bootloader, so it can be recognized and loaded and run by the real machine.
The usual way we let the bare metal run the ISO file is to burn the ISO file into the USB drive, then insert the USB drive into the computer, and select the USB drive startup item to run. But here I recommend using ventoy to make the boot disk. Ventoy will only format the USB disk once, then only need to copy the ISO file to the USB drive, which is very convenient. This is a screenshot of my machine.
With the help of the Go package management, we have successfully provided a Go language implementation of
libos so that ordinary Go programs can also run on bare metal. This is a very interesting attempt. I hope that the hardware driver can also be modularized into a Go package, so that you can customize your own kernel under the eggos framework as easy as importing a normal Go package!
许可协议 CC BY-NC-ND 4.0