Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

93 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nanemu

nanemu — минималистичная обертка для упрощения запуска на ядре Linux ELF-бинарников в QEMU.

Проект предназначен для:

  • ⚙️ Запуск кода на ядре Linux с минимальной настройкой (нужен только путь к папке с бинарями)
  • 🔬 Тестирования кода использующего низкоуровневые механизмы ОС, такие как eBPF, системные вызовы и т.п.
  • 🧪 Отладки поведения кода, поведение которого зависит от архитектуры и версии ядра Linux

Субсекундное время запуска на хост-системах с аппаратной поддержкой виртуализации и минималистичным ядром Linux.


Быстрый старт

  1. Установите QEMU

Для Alpine / Debian / Ubuntu:

sudo apt install qemu-system qemu-user-static

Официальная документация: QEMU installation guide

  1. Установите nanemu
GOBIN=$GOPATH/bin go install github.com/ebirukov/nanemu/cmd/nanemu@latest
  1. Скачайте ядро Linux (Опционально)

Например, для Alpine ARM64:

https://dl-cdn.alpinelinux.org/alpine/edge/releases/


Примеры использования

🔧 **Запуск одиночного файла init:**default

nanemu rootfs/init
nanemu -kernel kernel/arm64/linux-5.10.0-32-arm64 -arch arm64 rootfs/ init

🖥 Запуск с кастомными параметрами:

QEMU_BIN=/usr/bin/qemu-system-amd64 \
KERNEL_ARGS="initrd=/mybin cma=0 audit=0 nowatchdog nosmp maxcpus=1 ipv6.disable=1 net.ifnames=0 lsm= acpi=off ima_appraise=off" \
nanemu \
  -kernel kernel/amd64/linux-6.1.0-35-amd64 \
  -arch arm64
  -timeout 10s
  build/amd64/initramfs

Параметры

Флаг Тип Описание
-kernel string Путь к образу ядра Linux (обязательный, либо ENV KERNEL_PATH)
-arch string Целевая архитектура (по умолчанию: GOARCH)
-timeout duration Максимальное время выполнения QEMU (по умолчанию: 30m)
-loglevel string Уровень логирования при загрузке ядра (по умолчанию: 3)
-initrd string Создать образ диска начальной файловой системы initramfs (в формате cpio)
-memory string Размер памяти выделяемой QEMU
-smp string Кол-во ядер процессора выделямых QEMU

Переменные окружения

Переменная Описание
QEMU_BIN Путь к исполняемому файлу QEMU (по умолчанию: qemu-system-$ARCH)
QEMU_ARGS Дополнительные аргументы, передаваемые напрямую в QEMU
KERNEL_ARGS Дополнительные параметры загрузки ядра

Особенности

  • 🚀 Субсекундный запуск при использовании аппаратной поддержки виртуализации и минимальных ядрах
  • 🏗 Автоматически создаёт временный образ диска с фалйовой системой ext4 (при наличии модуля ядра VIRTIO_BLK), либо initramfs (в формате cpio)
  • 🧼 Автоматическая очистка временных файлов после завершения
  • 🛠 Поддержка архитектур amd64 и arm64

Пример: запуск собственной программы

  1. Возьмем hello linux программу:
package main

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

func main() {
	var uts syscall.Utsname
	syscall.Uname(&uts)
	osVersion := unsafe.String((*byte)(unsafe.Pointer(&uts.Release[0])), len(uts.Release))

	fmt.Printf(
		"Hello from process %d on linux kernel version: %s\n", os.Getpid(), osVersion)

	syscall.Reboot(syscall.LINUX_REBOOT_CMD_POWER_OFF)
}
  1. Скомпилируем под нужную архитектуру:
GOOS=linux GOARCH=arm64 go build -o build/hello-arm64 ./cmd/hello
  1. Запускаем с помощью nanemu:
nanemu \
  -kernel https://dl-cdn.alpinelinux.org/alpine/edge/releases/aarch64/netboot/vmlinuz-virt \
  -arch arm64 \
  -loglevel 6 \
  -initrd \
  example/build/hello-arm64
  1. Пример вывода:
2026/01/26 12:49:47 executing: /usr/bin/qemu-system-arm64 -serial mon:stdio -machine virt -cpu cortex-a53 -nographic -no-reboot -append rdinit=/hello-arm64 console=ttyAMA0 loglevel=6 -kernel kernel/vmlinuz-5.4.43-1-arm64 -initrd ./initramfs.cpio718173793
2026/01/26 12:49:47 process /usr/bin/qemu-system-arm64 started with pid: 2177874
[    0.000000] Linux version 6.18.7-0-virt (buildozer@build-edge-aarch64) (cc (Alpine 15.2.0) 15.2.0, GNU ld (GNU Binutils) 2.45.1) #1-Alpine SMP PREEMPT_DYNAMIC 2026-01-26 12:49:47
[    0.000000] Kernel command line: rdinit=/hello-arm64 console=ttyAMA0 loglevel=6
Hello from process 1 on linux kernel version: 6.18.7-0-virt
[    0.558718] reboot: Power down
2026/02/22 14:15:02 exit with code: 0

🧩 Расширения (extensions)

Механизм extensions позволяет динамически расширять параметры запуска nanemu, добавляя собственные опции QEMU без изменения исходного кода. Каждое расширение представляет собой отдельный файл в каталоге:

$HOME/.nanemu/extension/

Имя файла определяет флаг запуска, а содержимое файла — шаблон аргументов, добавляемых при выполнении QEMU.


Как это работает

При старте nanemu сканирует папку:

$HOME/.nanemu/extension/

Для каждого найденного файла создаётся дополнительный CLI-флаг. При указании этого флага при запуске nanemu, его содержимое автоматически подставляется в параметры QEMU.

Пример: файл console-unix создаёт флаг -console-unix. Если при запуске nanemu указать этот флаг, в QEMU будут добавлены аргументы из содержимого файла.


🧱 Пример: создание собственного расширения

  1. Создайте каталог для расширений (если его ещё нет):

    mkdir -p $HOME/.nanemu/extension
  2. Добавьте файл console-unix со следующим содержимым:

    # Подключение UNIX-сокета для консоли
    -chardev socket,path=%s,server=on,wait=off,id=unix0
    -device virtio-serial-pci
    -device virtserialport,chardev=unix0,name=unix.sock
  3. Запустите nanemu, указав новый флаг:

    nanemu \
      -kernel ../vmlinuz-amd64 \
      -rootfs ./build \
      -console-unix /tmp/qemu.sock
    ...

    👉 В результате nanemu автоматически добавит указанные строки в параметры запуска QEMU.


⚙️ Формат файла расширения

Каждый файл может содержать одну или несколько строк — шаблонов аргументов QEMU. В шаблоне можно использовать подстановку %s — она будет заменена на значение, переданное через одноимённый CLI-флаг.

Пример: файл $HOME/.nanemu/extension/port-fwd

# Проброс TCP-порта
-netdev user,id=net0,hostfwd=%s
-device virtio-net-pci,netdev=net0

Запуск:

nanemu -kernel vmlinuz -rootfs build -port-fwd tcp::8080-:22

Результат — в QEMU автоматически подставятся аргументы:

-netdev user,id=net0,hostfwd=tcp::8080-:22
-device virtio-net-pci,netdev=net0

🧠 Дополнительные возможности

  • Расширения можно создавать под разные архитектуры, добавив суффикс в имени файла. Например:

    usernet-amd64
    usernet-arm64
    

    В этом случае флаг -usernet будет активен только при запуске на соответствующей архитектуре.

  • Комментарии внутри файла (# или //) автоматически попадают в описание флага и отображаются при -h.


📋 Примеры готовых расширений

Имя файла Назначение
console-unix Привязка консоли QEMU к UNIX-сокету хоста
port-fwd Проброс TCP/UDP портов через -netdev user
usernet Конфигурация встроенной NAT-сети QEMU (user mode)

About

A minimalist, high-performance wrapper to execute ELF binaries across diverse Linux kernels and CPU architectures with sub-second startup latency

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages