MiOS es un sistema mínimo que arranca sobre el kernel Linux: en vez de usar
systemd, busybox o cualquier userspace tradicional, el PID 1 lo escribe
el propio proyecto en C, sin libc (-nostdlib -ffreestanding). Todo lo
que el sistema necesita —consola, lectura de /proc y /sys, sistema de
archivos, módulos del kernel y red— se pide directamente al kernel con
syscalls x86_64.
Tampoco usa la libc del anfitrión: MiOS trae su propia librería
(libmios.so.6) y su propio cargador dinámico (ld-mios.so.1), y sus
programas se compilan con mios-gcc contra un sysroot propio. Es el
primer escalón hacia el self-hosting.
El resultado es un init de ~43 KB (más libmios.so.6, ~30 KB, y el cargador,
~10 KB) que arranca desde una ISO con GRUB, monta /proc, /sys y /dev,
carga los módulos de red del initramfs, deja al usuario en una shell propia
con 34 comandos internos y la posibilidad de lanzar programas de /bin
(fork + execvp), más un /etc/autorun opcional. La ISO trae además su
propio compilador de C (tcc), que compila y enlaza dentro de MiOS.
================================
MiOS 0.5
Consola del sistema
================================
Escribe 'help' para ver los comandos.
Cargando modulos de red...
e1000 cargado
e1000e ya estaba cargado
MiOS> info
Salida real del /init de MiOS ejecutándose (banner, uname, info, hw,
net, routes, dev y help):
La captura viene de ejecutar el binario real
initramfs/initcon el kernel6.8.0-100-genericdel anfitrión. Por eso la carga de módulos aparece como no encontrado: en la ISO esos.kosí están dentro delinitramfs, en/lib/modules/<release>/.
| Área | Qué hace |
|---|---|
| Arranque | Monta proc, sysfs y devtmpfs; crea /dev/console si falta y muestra el banner |
| Sin libc del host | Trae su propia libc dinámica (libmios.so.6) y su propio cargador (ld-mios.so.1) |
| Toolchain propio | mios-gcc + sysroot (include/, crt1.o, libmios) para compilar programas para MiOS |
| Compilador dentro de MiOS | tcc 0.9.27 portado: /bin/tcc compila y enlaza sobre libmios.so.6 (sin binutils), y produce ejecutables que arrancan con ld-mios.so.1 |
| Self-hosting en C | Las fuentes de tcc van en la ISO (/usr/src/tcc/): tcc se compila a sí mismo dentro de MiOS y el tcc resultante compila programas |
| Editor de texto | edit: editor en consola a pantalla completa (estilo nano) para escribir ficheros dentro de MiOS |
| Shell propia | Parser de línea + registro de comandos por subsistemas (shell_register) |
| Módulos | Carga .ko con finit_module (sin modprobe), en varios pases para resolver dependencias |
| Hardware | CPU, núcleos, memoria, dispositivos PCI y NIC leyendo /proc y /sys |
| Sistema de archivos | getdents64, chdir, rename, unlink, mkdir, rmdir, copia con detección de EXDEV |
| Red | Sondeo de interfaces, direcciones y rutas por netlink; activar/apagar enlace |
| Consola | Salida con formato propio y buffer de historial (log) |
flowchart LR
A["GRUB<br/>iso/boot/grub/grub.cfg"] --> B["vmlinuz<br/>kernel Linux x86_64"]
B --> C["initramfs.cpio.gz<br/>/init + /lib"]
C --> D["/init — PID 1<br/>ELF dinámico"]
D -- "ld-mios.so.1" --> L["/lib/libmios.so.6<br/>libc propia de MiOS"]
D --> E["boot_setup_environment()<br/>monta /proc /sys /dev"]
D --> F["boot_load_modules()<br/>finit_module de los .ko"]
D --> G["shell_run()<br/>MiOS> "]
G --> H["core · sys · hw"]
G --> I["fs"]
G --> J["net (netlink)"]
G --> K["programas de /bin<br/>fork + execvp"]
K --> M["tcc<br/>compila .c dentro de MiOS"]
Estructura del código:
include/ cabeceras publicas (las que ve el programador de MiOS)
src/
├── mios.h cabecera común (versión y subsistemas)
├── lib/ libreria propia: consola, cadenas, memoria, errno, malloc, stdio,
│ scanf, formato, ctype, stdlib, dirent, stat, tiempo, procesos,
│ matematicas (libm: math.c) y fenv
├── kernel/ ABI del kernel x86_64 y envoltorios de syscall
├── crt/ crt1.o: el _start de los programas normales
├── ld/ ldmios.c: el cargador dinámico propio (ld-mios.so.1)
├── core/ main, boot, shell, prog (lanzar programas), modules y comandos sys/shell/hw
├── fs/ archivos y comandos del sistema de archivos
└── net/ red: netlink, sondeo de interfaces/rutas y comandos
userland/ programas de MiOS que van a /bin (hola, args, selftest, runlog, edit)
tools/ scripts de apoyo (fetch-tcc.sh, build-tcc.sh)
third_party/ fuentes de terceros (tcc; no se versionan)
examples/ ejemplos para probar el toolchain (hola.c, tcc-hola.c, ...)
| Módulo | Archivos clave |
|---|---|
| Entrada y arranque | src/core/main.c, src/core/boot.c, src/core/modules.c |
| Librería propia | src/lib/*.c, include/*.h |
| Cargador dinámico | src/ld/ldmios.c |
| Shell | src/core/shell.c, src/core/cmd_shell.c |
| Procesos | src/core/prog.c (fork/execvp/waitpid) |
Programas de /bin |
userland/*.c → initramfs/bin/ |
| Compilador propio | third_party/tcc + tools/build-tcc.sh → /bin/tcc |
| Syscalls | src/kernel/syscall.c, src/kernel/syscall.h |
| Sistema de archivos | src/fs/file.c, src/fs/cmd_fs.c |
| Red | src/net/netlink.c, src/net/net.c, src/net/cmd_net.c |
34 comandos (salida real de help)
Shell
| Comando | Descripción |
|---|---|
help |
Muestra los comandos |
clear |
Limpia la pantalla |
echo |
Repite el texto indicado |
exit |
Avisa de que el PID 1 no termina |
Sistema
| Comando | Descripción |
|---|---|
info |
Información del sistema |
uname |
Información del kernel |
uptime |
Tiempo desde el arranque |
mods |
Módulos del kernel cargados |
loadmods |
Carga los módulos de red |
loadmod |
Carga un módulo: loadmod <ruta.ko> |
drivers |
Estado de los drivers de red |
klog |
Mensajes del kernel (/dev/kmsg) |
log |
Historial de la consola |
reboot |
Reinicia la máquina |
poweroff |
Apaga la máquina |
Hardware
| Comando | Descripción |
|---|---|
hw |
Estado del hardware (CPU, RAM) |
pci |
Dispositivos PCI y su driver |
nic |
Dispositivo PCI de red y driver |
Archivos
| Comando | Descripción |
|---|---|
pwd |
Directorio actual |
ls |
Lista archivos |
cd |
Cambia de directorio |
cat |
Muestra un archivo |
cp |
Copia archivos |
mv |
Mueve o renombra archivos |
rm |
Elimina archivo o directorio |
mkdir |
Crea un directorio |
rmdir |
Elimina un directorio |
touch |
Crea un archivo vacío |
Red
| Comando | Descripción |
|---|---|
net |
Estado de las interfaces de red (net <if> para detalle) |
routes |
Tabla de rutas |
wifi |
Interfaces wifi detectadas |
netup |
Activa una interfaz: netup <if> |
netdown |
Apaga una interfaz: netdown <if> |
dev |
Interfaces en /sys/class/net |
Ejecutar programas: cualquier orden que no sea uno de esos comandos internos se ejecuta
como programa (igual que en un shell de verdad): se busca en PATH (/bin:/usr/bin), se
lanza con fork + execvp y se espera su fin. Los programas que trae la ISO son:
| Programa | Descripción |
|---|---|
hola |
Saludo de ejemplo (usa printf, uname, getpid) |
args |
Imprime sus argumentos y termina con código = argc |
selftest |
Autoprueba de MiOS (fork/waitpid, execv/execvp, pipe, fds heredados); informa con cons_*, así que su salida llega también al puerto serie |
runlog |
Ejecuta otro programa y copia su salida (stdout y stderr) a la pantalla y al puerto serie: runlog tcc -o /tmp/hola /usr/src/hola.c |
tcc |
El compilador de C de MiOS (tcc 0.9.27, ver más abajo) |
edit |
Editor de texto en consola (estilo nano): edit fichero.c; Ctrl-S guarda y Ctrl-Q sale (ver más abajo) |
MiOS> hola
Hola desde un programa de /bin de MiOS!
MiOS> args uno dos
args: 3 argumentos
argv[0] = args
argv[1] = uno
argv[2] = dos
MiOS: 'args' termino con codigo 3
Además, /etc/autorun (opcional) contiene órdenes que la shell ejecuta al arrancar, una por
línea (# comenta); en la ISO va sin órdenes, sólo con ejemplos comentados.
Dependencias (una vez):
sudo apt install gcc make binutils cpio gzip grub-pc-bin grub-common xorriso mtoolsEjecutar el build completo (compila → empaqueta el initramfs → genera la ISO →
monta el sysroot):
chmod +x build.sh
./build.shEl script hace nueve pasos:
- Compila
libmios.so.6, la libc propia, desdesrc/lib/*.c+src/kernel/*.c(-fPIC). - Compila
ld-mios.so.1, el cargador dinámico propio (src/ld/ldmios.c), estático. - Compila y enlaza
init(src/core/,src/fs/,src/net/) contralibmios. - Monta el sysroot (
mk-sysroot.sh), que hace falta para compilar conmios-gcc. - Compila los programas de
userland/*.cainitramfs/bin/(los que lanza la shell). - Compila
tcc(tools/build-tcc.sh) y lo mete en el initramfs:/bin/tcc, sus cabeceras ylibtcc1.aen/lib/tcc/, las cabeceras públicas en/usr/include, el arranque (crt1.o,crti.o,crtn.o) en/usr/liby los enlaces/lib/libc.so,/lib/libm.so. Si faltan las fuentes detcc(third_party/tcc), avisa y sigue: MiOS no necesitatccpara arrancar. - Copia la librería y el cargador a
initramfs/lib/. - Empaqueta
initramfs/eniso/boot/initramfs.cpio.gzy generaMiOS.isocongrub-mkrescue. - Prueba de humo: compila
examples/hola.cconmios-gcc.
Las fuentes de tcc no se versionan; se bajan fijando la versión con:
./tools/fetch-tcc.sh # clona third_party/tcc en el tag release_0_9_27La ISO trae el Tiny C Compiler (tcc 0.9.27) portado a MiOS: corre sobre libmios.so.6, trae
su propio ensamblador y enlazador (no necesita binutils) y compila programas contra las cabeceras
y la libc de MiOS.
MiOS> tcc -o /tmp/hola /usr/src/hola.c # compila /usr/src/hola.c (ejemplo incluido)
tcc: compilacion correcta -> /tmp/hola
MiOS> /tmp/hola # ...y se ejecuta como cualquier programa
Hola: programa compilado con tcc dentro de MiOS (argc=1)
tcc dice siempre cómo ha ido, tanto al terminar bien como al fallar, en vez de quedarse
callado o dejar los errores sueltos:
MiOS> tcc -o /tmp/malo /usr/src/roto.c
/usr/src/roto.c:2: error: 'x' undeclared
tcc: la compilacion ha fallado
MiOS: 'tcc' termino con codigo 1
Ese mensaje lo añade un parche de tres líneas de MiOS (tools/tcc-mios-info.inc) que el build
aplica a una copia de tcc.c (las fuentes de third_party/ no se tocan); como la copia
parcheada es también la que se instala en /usr/src/tcc/tcc.c, el tcc que MiOS compila a sí
mismo informa igual.
Para ver también los mensajes de tcc en el puerto serie (en MiOS la salida de un programa
va a la pantalla, no al puerto serie) se usa runlog:
MiOS> runlog tcc -o /tmp/hola /usr/src/hola.c
Las fuentes de tcc van dentro de la ISO (/usr/src/tcc/), así que el compilador puede
compilarse a sí mismo sin salir de MiOS:
MiOS> runlog tcc -o /tmp/tcc2 /usr/src/tcc/tcc.c # tcc compila tcc
MiOS> runlog /tmp/tcc2 -o /tmp/hola2 /usr/src/hola.c # ...y el tcc-resultante compila un programa
MiOS> runlog /tmp/hola2
Eso es el self-hosting en C: la cadena de compilación de MiOS ya no depende del VPS para
reconstruirse (el tcc de la ISO compila otro tcc funcional). El siguiente escalón del plan son
las binutils propias y GCC (ver docs/PLAN-TOOLCHAIN.md).
La ISO trae un editor de texto en consola (/bin/edit), para escribir y retocar programas
dentro de MiOS sin salir de él:
MiOS> edit /tmp/hola.c
Se abre a pantalla completa, estilo nano: arriba el fichero, y abajo la línea de estado
(fichero, línea/columna y si hay cambios sin guardar) y la ayuda.
| Teclas | Qué hace |
|---|---|
flechas, Inicio, Fin, AvPag, RePag |
mover el cursor |
Enter |
partir la línea |
Retroceso, Supr |
borrar |
Tabulador |
espacios hasta el múltiplo de 8 |
Ctrl-S |
guardar |
Ctrl-Q (o Ctrl-C) |
salir (pide confirmación si hay cambios sin guardar) |
Ctrl-K |
borrar la línea entera |
Ctrl-L |
repintar la pantalla |
Ctrl-G |
mostrar/ocultar la ayuda |
Mientras se edita, la consola se pone en modo crudo (cfmakeraw: sin eco, sin modo canónico
y sin señales, para poder leer tecla a tecla) con los ioctl de termios de siempre, y al salir
se deja como estaba. Por eso el editor no conviene ponerlo en /etc/autorun: se quedaría
esperando teclas y bloquearía el arranque.
Trae dos pruebas automáticas que no necesitan consola interactiva (útiles desde runlog y desde
/etc/autorun):
MiOS> runlog edit --selftest # motor de edicion: cargar, insertar, partir, pegar, guardar...
MiOS> runlog edit --ttytest # ioctl de termios y modo crudo de la consola
El ciclo completo dentro de MiOS es escribir con edit, compilar con tcc y ejecutar:
MiOS> edit /tmp/hola.c # se escribe y se guarda con Ctrl-S; se sale con Ctrl-Q
MiOS> tcc -o /tmp/hola /tmp/hola.c
tcc: compilacion correcta -> /tmp/hola
MiOS> /tmp/hola
Cualquier programa en C se compila contra el sysroot de MiOS, sin libc del anfitrión:
./mios-gcc hola.c -o holamios-gcc ya pone el sysroot, los flags freestanding y el enlazado con crt1.o,
-lmios y -Wl,--dynamic-linker=/lib/ld-mios.so.1. El binario pide
libmios.so.6, igual que init.
#include <stdio.h> /* los nombres de siempre... */
#include <mios.h> /* ...y la API propia: cons_*, mios_* */
int main(int argc, char **argv) {
printf("Hola desde MiOS (%d argumentos)\n", argc);
return 0;
}Como las llamadas al kernel son las mismas de Linux x86_64 (el truco del ABI), el binario también corre en el propio VPS, dentro del chroot del sysroot:
cp hola sysroot/ && sudo chroot sysroot /holaEn Windows, mios-cc.bat hola.c compila en el VPS con mios-gcc y deja el
binario en mios-bin\ (con run como último argumento, además lo ejecuta).
Ejemplos incluidos: examples/hola.c, examples/fmt.c (prueba del motor de
formato que usa la consola), examples/fase2.c (prueba grande de la libc:
malloc/FILE/qsort/getenv/stat/dirent/tiempo...), examples/fase3.c
(prueba de la biblioteca matemática y de fenv), examples/fase4.c (procesos:
fork/wait, execv/execvp, pipe y descriptores heredados; se ejecuta en el
chroot del sysroot con tools/test-fase4.sh) y examples/tcc-hola.c (prueba del
tcc de dentro de MiOS; el build lo copia a /usr/src/hola.c).
Los programas «de serie» que la shell puede lanzar están en userland/ y el
build los deja en initramfs/bin/ (/bin dentro del SO).
sudo apt install inotify-tools
./watch.shwatch.sh vigila src/ y vuelve a lanzar el build cada vez que guardas un
.c/.h.
Arranca la ISO en una máquina virtual:
qemu-system-x86_64 -m 1G -cdrom MiOS.isoEn GRUB elige la entrada de MiOS y espera la consola. En VMware funciona con la
NIC e1000, que es la que se ve en la captura (ens33 → e1000).
- Sin libc del anfitrión: MiOS trae su propia librería dinámica
(
libmios.so.6) y su propio cargador (ld-mios.so.1); no se enlaza con la libc del sistema. La consola escribe con sus propias rutinas de formato yerrnose resuelve con__errno_location(), como en glibc. - Programas:
mios-gccusa--sysrooty genera ejecutables ET_EXEC (no PIE) conPT_INTERP=/lib/ld-mios.so.1, igual queinit. Desde la Fase 2 la libc tiene yamalloc,FILE(stdin/stdout/stderr),qsort,getenv,dirent,stat,time,sscanf... y el cargador soportaR_X86_64_COPY. Desde la Fase 3 hay además biblioteca matemática propia (<math.h>+<fenv.h>);-lmfunciona porque el sysroot enlazalibm.soalibmios.so.6. Desde la Fase 4 la shell lanza programas (fork+execvp+waitpid, buscando enPATH), concd/pwdy un/etc/autorunopcional. La salida de un programa va a sustdout= consola del sistema (tty0); los mensajes de MiOS se duplican además al puerto serie (/dev/ttyS0). - Compilador dentro de MiOS (Fase 5):
tcc0.9.27 corre sobrelibmios.so.6y compila contra las cabeceras públicas de MiOS (/usr/include), enlazando con/usr/lib/crt1.o+-lc(que es/lib/libc.so→libmios.so.6). Su configuración la generatools/build-tcc.sh(CONFIG_TCC_ELFINTERP=/lib/ld-mios.so.1,CONFIG_TCCBOOT, sindlopen), y el build lo instala en elinitramfs. Al compilarlo,build-tcc.shle aplica un parche de tres líneas (tools/tcc-mios-info.inc) para que diga el resultado de la compilación (tcc: compilacion correcta -> .../tcc: la compilacion ha fallado). Como la salida de un programa no llega al puerto serie, para ver los errores del compilador (o de cualquier programa) existerunlog: ejecuta el programa con una tubería comostdout/stderry lo copia a la pantalla y a/dev/ttyS0. - Editor de texto (Fase 6b):
edites el primer programa de MiOS que necesita leer teclas una a una:include/termios.h+src/lib/termios.cañaden a la libctcgetattr/tcsetattr/cfmakeraw/tcflush(los mismosioctlque ya usabaisatty). El editor pone la consola en modo crudo mientras trabaja, la deja como estaba al salir y pinta la pantalla con códigos ANSI (el terminal virtual del kernel los entiende). Carga el fichero entero en memoria; al cargar, las tabulaciones se expanden a espacios y el fichero guardado acaba siempre en\n. - PID 1: MiOS no puede terminar;
exitsolo lo recuerda.rebootypoweroffusanreboot(2)con los magic numbers. - Módulos:
boot_load_modules()prueba hasta 3 pasadas para respetar el orden de dependencias (por ejemplomiiantes depcnet32), e informa de cada.kocomo cargado, ya estaba cargado, no encontrado o error. - Red: el sondeo usa
NETLINK_ROUTE(RTM_GETLINK,RTM_GETADDR,RTM_GETROUTE) ynetup/netdowncambian el estado conRTM_NEWLINK. - Versión del kernel: la ruta de los módulos se construye con el
releasedeuname(), así que no hay versión fijada a mano.
- Guía: kernel, initramfs e ISO
- Guía: init en C estático para initramfs
- Plan: toolchain propio (tcc → GCC → self-hosting)
- Progreso del proyecto
| Archivo | Uso |
|---|---|
docs/assets/mios-banner.png |
Banner principal (1600×480) |
docs/assets/mios-logo.png |
Logo / icono (512×512) |
docs/assets/mios-shell.png |
Captura real de la consola |
docs/assets/*.svg |
Fuentes vectoriales del logo y el banner |
MiOS está en desarrollo activo y es experimental: se prueba en máquinas
virtuales (VMware / QEMU). La ISO generada (MiOS.iso, ~20 MB) no se
versiona en el repositorio (*.iso está en .gitignore); se regenera con
./build.sh.
github.com/Chichimokers/MiOS


