Binary Compatibility In Unikraft
Let’s hack and run our favorite applications on top of Unikernels using the Unikraft toolkit. Unikernel can enhance the performance by increasing the speed and lowering the response time and at the same time providing high-level security. To know more about Unikernels, kindly visit my previous blogs: https://chococandy63.github.io/chococandy-blog/tags/unikernel/
In this blog, I will teach you about binary compatibility in Unikraft.
We can port applications to Unikraft(future blogs will show you how you can port applications to Unikraft) but that will take time and might be a little complex if you don’t like to play with low-level C stuff.
No worries, we have an alternate solution for this which is to take the pre-complied application binaries of existing applications/command line utilities and run them on top of Unikernel using Unikraft tooling.
I have done the same for the grep
command line utility. You can see my work here: https://github.com/unikraft/dynamic-apps/pull/71
Note: These applications are Linux executables and they are not ported to Unikraft. They just run it on top of unikraft as Unikernels.
Let us go through the steps that I followed in order to run grep
on Unikraft.
Commands to follow
which grep
Outputs: /usr/bin/grep
file /usr/bin/grep
Outputs: /usr/bin/grep: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=492b58120241302624ff65d4f8867f3e82713545, for GNU/Linux 3.2.0, stripped
Let’s take another example of a little more complex application like-
Suppose we want to run a Rust application on Unikraft, we check the file information using file
command -> outputs as 64 bit ELF
.
Internals
We run ldd app-name
which shows the shared object dependencies. In order for app-name
to run properly we need these dependencies. We can also see the file systems in a more structured way by using a tree
command.
We found a file named ld-linux-x86-64.so.2
which is basically a dynamic linker/loader. This is a system loader app that Linux calls when loading stuff in memory. Every time you run any executable, Linux will run this program and load all the dependencies that the executable has. So, we also want to do the same when we are running an application on Unikraft.
We have run.sh
script inside run-app-elfloader
repository which is a wrapper on top of a QEMU, this script just makes it easier to run the application on top of QEMU without mentioning/configuring the QEMU flags(because those flags are being handled internally by run.sh
script).
To run any application- ./run.sh -r ../dynamic-apps/lang/rust/ -k ./run-app-elfloader_qemu-x86_64_plain /filename
You probably know by now what run.sh script does, moving to the -r
flag which is used to link the location of the app