El propósito de esta "wiki", documentación web, guía, como le digas, es usarla como ayuda-memoria
personal
para el desarrollo del kernel.
No tiene que ser una página ultra estética, pero me estoy esforzando para que no se note que la hice
con html, css y js vanilla como la de algún proyecto aficionado
que anda por ahí.
Un kernel de sistema operativo mínimamente funcional (todo el Kernel Space más un user space mínimo)
puede andar fácilmente en las 15.000 líneas de código por lo que, como verás;
es humanamente imposible memorizar y comprender todo el flujo del kernel por mí mismo. Además son
muchos subsistemas complejos trabajando a bajo nivel juntos para intermediar entre hardware y
software.
Este cálculo es automático y se hace mediante una api que cuenta la cantidad de líneas de código que tiene el kernel (.c, .h, .asm, .rs y .cpp)
Esto merece que dejes una estrella en el repo
IR0 es un kernel de sistema operativo multipropósito desarrollado
desde cero para arquitectura x86-64 escrito en C,
C++,
Rust y ASM. El kernel core está en C, los device drivers en Rust
(para memory safety), y componentes avanzados como schedulers en C++ (para templates y RAII).
Lo estoy creando para aprender más sobre sistemas operativos y poder usarlo como materia
prima para otro proyecto que replica a WSL2 pero con mi propio kernel.
No descarto escalarlo lo suficiente como para hacerlo usable en servidores mínimos o incluso IoT,
pero entiendo que eso es al largo (larguísimo) plazo.
Este
es su Repositorio de GitHub.
Discord
community
make first-boot / make run)/dev/fb0 y eventsLínea: 0.0.1 (pre-release hacia el ship estable)
Arquitectura: x86-64 (primaria); aarch64 en el árbol
Producto userspace: ISD (repo hermano) — rootfs, runit, BusyBox
Bootloader: GRUB / multiboot
Licencia: GNU GPL v3.0
Tipo: Kernel monolítico modular
Enfoque actual: uniprocessor en QEMU/VM, producto vía ISD
A diferencia de kernels como kernel NT (Híbrido) de Microsoft, Redox-OS
(Microkernel),
o el mismo MINIX kernel (microkernel), IR0 se basa en una arquitectura más
similar a la que tiene Linux, que es monolítico.
Sin embargo, mi argumento principal es el del rendimiento. Entiendo que alguien podría venir y
señalar que, como todo monolito, si un subcomponente se rompe, se cae todo el sistema (y
tendría razón)
pero lo que respondo a eso es que "¿De qué me sirve a mí que el kernel soporte seguir sin
filesystem si no puedo hacer nada práctico sin él?", es decir, no tiene sentido que el
kernel
continúe funcionando sin uno de sus componentes clave corriendo.
Por eso no veo mejor alternativa (por ahora) que el patrón monolítico. Y además me ahorra el tener que interconectar
subsistemas clave entre sí con IPC, lo que impacta de una en el rendimiento del Sistema Operativo.
No es
perfecto, pero es estable. No es del todo trazable y requiere escalar de a poco, pero si escala bien
rinde mucho.
Sin embargo yo también tengo desacuerdos con la filosofía UNIX. Ellos (entre otras cosas y de forma resumidísima)
consideran
que si algo falla, que falle bien. Lo que en términos kernelísticos sería: Si se rompe el
scheduler, Panic() directo. Si tenés corrupción en memoria (en espacio de kernel),
Panic.
Y no es que lo cuestiono por que sí, simplemente pregunto (aunque sin soluciones todavía) "¿Por
qué no rescatar el sistema en tiempo de Panic()?, o por lo menos hacer el intento".
Mas allá del punto filosófico y para resumir, el kernel es monolítico porque es más performante y
siento que las piezas clave del núcleo deben trabajar sin overhead.
Sin embargo, si en el futuro necesitara integrar algún subsistema específico de forma híbrida,
seguramente sería pragmático.
Yo sé que hablo como si IR0 fuera usado por miles de personas y toda la historia, pero me voy a dar
el lujo de opinar al respecto.
Entonces, el punto es que el kernel space tiene que ser sólo habitable por subsistemas
que trabajen en ese Entorno,
nada mas.
Entiendo que hayan ciertos fabricantes preocupados por la seguridad de sus
clientes que,
casualmente, tienen acceso a toda interrupción que el usuario haga (saben qué teclas presionás,
el tiempo de tu sesión cada vez que prendés la compu, etc.) Y todo eso porque tienen
software funcionando en el kernel space con todos los privilegios que eso
implica.
RING 0 es únicamente para el kernel. Todo lo que venga del RING 3
se comunica con syscalls(), fin del comunicado.
Para que IR0 funcione como soporte para servidores básicos y aplicaciones IoT, necesito
soporte de red fundamental pero sin la complejidad masiva del stack completo de
Linux.
En el Kernel Linux son mas o menos 1.500.000 de líneas de código SÓLO LA PILA DE RED
COMPLETA. En lugar de intentar portar todo eso, he decidido usar un enfoque más
pragmático:
Implementación básica con librería IoT:
Cómo la estructura de archivos puede cambiar constantemente, prefiero que la consultes en el Repositorio de GitHub.
- Rama principal con código estable y testeado.
- Rama de desarrollo activo donde se implementan y testean nuevas features.
- La agrego porque es la rama donde se crean feats que despues pasan al upstream mergeando a dev . Es la más inestable de todas porque es donde se integra código nuevo que también debe ser testeado y revisado antes de llegar a merge.
- En esta rama, se integran features lo suficientemente inestables como para terminar en mainline pero que pueden tener potencial a futuro.
Línea: 0.0.1 (pre-release)
Arquitectura: x86-64 primaria; aarch64 en el árbol
Userspace: ISD (runit + BusyBox)
Licencia: GNU GPL v3.0
Tipo: Kernel monolítico modular
Ubicación: mm/pmm.c, mm/allocator.c, mm/paging.c
El subsistema de gestión de memoria proporciona tres capas de asignación y gestión de memoria: Administrador de Memoria Física (PMM) para asignación de frames, asignador de heap para memoria dinámica del kernel, y sistema de paginación para memoria virtual y aislamiento de procesos.
Ubicación: mm/pmm.h, mm/pmm.c
El PMM gestiona frames de memoria física (páginas de 4KB) usando un asignador basado en bitmap:
pmm_alloc_frame() - Asigna un frame, pmm_free_frame() - Desasigna un framepmm_stats() - Proporciona conteos de frames totales/usados/libresUbicación: includes/ir0/kmem.h, mm/allocator.c
Asignación dinámica de memoria para código del kernel usando una free-list con boundary tags:
kmalloc(), kmalloc_aligned(), krealloc(), kfree(), kfree_aligned()Ubicación: mm/paging.h, mm/paging.c
Gestión de memoria virtual y aislamiento de procesos a través de directorios de página separados:
map_page(), unmap_page(), create_process_page_directory()0x000000 - 0x100000 Código de arranque, código del kernel 0x100000 - 0x800000 Heap del kernel (crece hacia arriba) 0x800000 - 0x2000000 Frames gestionados por PMM (8MB-32MB, 24MB) 0x2000000+ Datos del kernel, stacks
brk()PAGE_COW, make smoke-mm-cow-lazy)copy_*_user), no memcpy crudoUbicación: kernel/process.c, kernel/process.h
El subsistema de gestión de procesos maneja el ciclo de vida completo de los procesos en el kernel IR0, incluyendo creación, ejecución, terminación y relaciones padre-hijo. Proporciona aislamiento de procesos a través de directorios de página separados y soporta comunicación entre procesos basada en señales.
Cada proceso está representado por una estructura process_t que contiene:
wait() todavíaprocess_spawn() - Crea un nuevo proceso determinísticamente con un punto de entrada y nombre especificados:
process_exit() - Termina el proceso actual:
process_wait() - Espera a que un proceso hijo termine y recupera su estado de salida:
El subsistema de procesos se integra con el sistema de señales para comunicación entre procesos y manejo de errores:
Cada proceso tiene su propio directorio de página (registro CR3) para aislamiento de memoria:
brk() (heap por proceso)SYS_EXIT(0) - Terminación de proceso SYS_WRITE(1) - Escribir a descriptor de archivo SYS_READ(2) - Leer de descriptor de archivo SYS_GETPID(3) - Obtener ID de proceso SYS_GETPPID(4) - Obtener ID de proceso padre SYS_LS(5) - Listar contenidos de directorio SYS_MKDIR(6) - Crear directorio SYS_PS(7) - Mostrar lista de procesos SYS_WRITE_FILE(8) - Escribir archivo al filesystem SYS_CAT(9) - Mostrar contenidos de archivo SYS_TOUCH(10) - Crear archivo vacío SYS_RM(11) - Eliminar archivo SYS_FORK(12) - Crear proceso hijo SYS_WAITPID(13) - Esperar proceso hijo SYS_RMDIR(40) - Eliminar directorio SYS_MALLOC_TEST(50) - Test de asignación de memoria SYS_BRK(51) - Cambiar break del heap SYS_SBRK(52) - Incrementar break del heap SYS_MMAP(53) - Mapeo de memoria SYS_MUNMAP(54) - Desmapear memoria SYS_MPROTECT(55) - Cambiar protección de memoria SYS_EXEC(56) - Ejecutar programa
/dev/consoleminimal, development, desktopmake first-boot PROFILE=minimal — bootstrap ISD + imagenmake run PROFILE=minimal — QEMU GTK con disco ISDIR0/ y ISD/virtio.md, smokes de sesión)make kernel-x64.bin / make run — build y QEMUmake menuconfig — drivers, FS, scheduler, initarch-guard, matriz de build, smokes QEMU / KTM/dev/fb0, TinyX, DoomDocumentation/ en este repo (espejo de IR0)Enfoque actual: uniprocessor en QEMU/VM, producto userspace vía ISD.
print(), write(), etc. por que no hay sistema operativo que
responda a esas funciones . Vos sos el
sistema operativo. por eso, en el repo tengo la carpeta de dependencias "includes".
snake_case()UPPER_CASEstruct_name_tg_variable_nameCONSTANT_NAME#INCLUDE -ir0/Lib.h - (se estan migrando a ese formato)Intentamos seguir el estilo de código del kernel Linux, pero con algunas adaptaciones específicas para este proyecto. Estas son convenciones deseables, no reglas estrictas (excepto por el estilo de llaves).
/* ... */ sobre los
de una línea //.if de una sola línea no deben usar llaves.goto para lógica de limpieza cuando
múltiples puntos de salida comparten el mismo código de limpieza./*
* Ejemplo de una función siguiendo las convenciones de IR0
* Note las llaves estilo Allman y los comentarios multilínea
*/
int process_data(struct data_t *data)
{
if (!data)
return -1; /* If de una línea sin llaves */
char *buffer = kmalloc(1024);
if (!buffer)
{
/*
* Se usan llaves aquí porque el bloque
* contiene múltiples líneas o es complejo
*/
return -ENOMEM;
}
if (prepare_buffer(buffer) < 0)
goto cleanup; /* Uso de goto para manejo de errores/limpieza */
/* ... lógica de procesamiento ... */
kfree(buffer);
return 0;
cleanup:
kfree(buffer);
return -1;
}
Los archivos de cabecera deben contener prototipos de funciones, definiciones de estructuras y documentación detallada en comentarios.
#ifndef _IR0_EXAMPLE_H
#define _IR0_EXAMPLE_H
/*
* struct example_t - Representa una estructura de ejemplo
* @id: Identificador único
* @value: Valor asociado
*/
typedef struct
{
int id;
int value;
} example_t;
/*
* process_example - Procesa la estructura de ejemplo
* @ex: Puntero a la estructura
* Retorna: 0 en éxito, código de error negativo en fallo
*/
int process_example(example_t *ex);
#endif
IMPORTANTE: Antes de compilar, se recomienda verificar que todas las dependencias estén correctamente instaladas:
make deptest
Este comando verificará la presencia de todas las herramientas necesarias:
El script detecta automáticamente tu plataforma y proporciona instrucciones específicas de instalación si falta alguna herramienta.
IR0 ahora soporta desarrollo en tres lenguajes:
# Instalar Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Agregar componentes necesarios rustup component add rust-src rustup target add x86_64-unknown-none # Verificar instalación rustc --version cargo --version
# Debian/Ubuntu sudo apt-get install g++ # Arch Linux sudo pacman -S gcc # Verificar instalación g++ --version
# Debian/Ubuntu sudo apt-get install build-essential nasm qemu-system-x86 grub-pc-bin python3 # Arch Linux sudo pacman -S base-devel nasm qemu grub python
| Comando | Descripción |
|---|---|
make ir0 |
Compilación completa: kernel ISO + programas userspace |
make kernel-x64.bin |
Compilar solo el binario del kernel |
make kernel-x64.iso |
Crear imagen ISO booteable |
make userspace-programs |
Compilar solo programas de userspace |
make clean |
Limpiar todos los artefactos de compilación |
make userspace-clean |
Limpiar solo programas userspace |
| Comando | Descripción |
|---|---|
make run |
Ejecutar con GUI + disco virtual (recomendado) |
make run-debug |
Ejecutar con GUI + salida de debug serial |
make debug |
Ejecutar con logging detallado de QEMU |
make run-nodisk |
Ejecutar sin disco virtual |
make run-console |
Ejecutar en modo consola (sin GUI) |
Configuración QEMU:
-no-reboot -no-shutdownqemu_debug.log| Comando | Descripción |
|---|---|
make create-disk |
Crear imagen de disco virtual (disk.img) |
make delete-disk |
Eliminar imagen de disco virtual |
Especificaciones del disco:
scripts/create_disk.sh| Comando | Descripción |
|---|---|
make deptest |
Verificar todas las dependencias del sistema |
make help |
Mostrar ayuda completa del Makefile |
make menuconfig |
Lanzar configuración del kernel (ncurses) |
make unibuild FILE=<archivo> |
Compilar archivo individual |
Sistema unibuild - Compilación Multi-Lenguaje:
El sistema unibuild ahora soporta compilar archivos en C, C++, y Rust con flags específicos:
# Compilar archivos C (por defecto) make unibuild FILE=kernel/memory/kmalloc.c # Compilar archivos C++ make unibuild -cpp FILE=kernel/scheduler/advanced_sched.cpp # Compilar drivers Rust make unibuild -rust FILE=drivers/network/rtl8139.rs # Cross-compilación a Windows (desde Linux) make unibuild -win FILE=kernel/file.c make unibuild -win -cpp FILE=kernel/component.cpp make unibuild -win -rust FILE=drivers/driver.rs # Compilar múltiples archivos make unibuild FILES="fs/ramfs.c fs/vfs.c"
Flags disponibles:
-cpp - Usar compilador C++ (g++)-rust - Usar compilador Rust (rustc)-win - Cross-compilar a Windows usando MinGW-w64Los flags se pueden combinar para diferentes casos de uso (ej: -win -cpp para
cross-compilar C++ a Windows).
make deptestmake ir0make create-disk (primera vez)make runmake run-debug
- En esta sección se detallan los principales subsistemas que componen el kernel
IR0,
su estado actual de desarrollo y las características técnicas de cada uno.
La mejor forma de entender el funcionamiento interno es revisando el código fuente en el
Repositorio de GitHub.
Ubicación: kernel/rr_sched.c, kernel/rr_sched.h
El subsistema de planificación gestiona la asignación de tiempo de CPU entre procesos. IR0 implementa actualmente un planificador Round-Robin simple que proporciona tiempo compartido justo entre todos los procesos listos. El planificador se integra con los subsistemas de gestión de procesos y manejo de señales.
El planificador Round-Robin mantiene una lista enlazada circular de procesos:
rr_task_t, cada uno contiene un process_t*rr_add_process() - Agrega un proceso a la cola del planificador:
rr_task_trr_schedule_next() - Realiza cambio de contexto al siguiente proceso:
handle_signals() antes del cambio de contextojmp_ring3(), subsiguientes usan switch_context_x64()El cambio de contexto guarda/restaura el estado CPU (kernel/scheduler/switch/switch_x64.asm):
Implementación actual:
El planificador llama handle_signals() antes de cada cambio de contexto:
VFS centralizado: la política (open/read/write/chmod/chown) vive en
fs/vfs.c; los backends implementan las operaciones.
Block: ATA + AHCI. Detalle en Documentation/FILESYSTEM.md.
Sistema robusto de manejo de interrupciones y excepciones que garantiza la estabilidad del kernel y proporciona una interfaz limpia para el manejo de eventos de hardware y software.
Archivos: interrupt/idt.c, interrupt/interrupt.asm, interrupt/isr_handlers.c, interrupt/irq.c
Sistema de inicialización que prepara el entorno para la ejecución del kernel, manejando la transición desde el bootloader hasta el espacio de usuario.
Archivos: boot/boot.asm, boot/kmain.c, boot/arch.c, boot/kernel_start.c
Sistema avanzado de gestión de memoria que proporciona aislamiento entre procesos, optimización de rendimiento y protección contra accesos no autorizados.
Archivos: mm/page_alloc.c, mm/slab.c, mm/vmalloc.c, mm/protection.c
Pila de red completa basada en Linux pero optimizada para el kernel IR0, proporcionando soporte para protocolos modernos y optimizaciones específicas.
Estado: Integración con Linux networking stack
Archivos: net/tcp.c, net/udp.c, net/socket.c, net/protocols/
Framework modular para el desarrollo y gestión de drivers de hardware, con soporte para hot-plugging y gestión automática de dispositivos.
Archivos: drivers/core.c, drivers/block/, drivers/char/, drivers/net/
Framework integral de seguridad que protege el kernel y los procesos de usuarios, implementando múltiples capas de protección y auditoría de seguridad.
Archivos: security/capability.c, security/seccomp.c, security/lsm/, security/audit.c
Sistema avanzado de gestión de energía que optimiza el consumo de batería en dispositivos móviles y reduce el consumo energético en servidores, manteniendo el rendimiento.
Archivos: power/suspend.c, power/cpuidle.c, power/thermal.c, power/battery.c
Subsistema de virtualización que permite ejecutar múltiples sistemas operativos simultáneamente, con soporte para contenedores y máquinas virtuales completas.
Archivos: virt/kvm/, virt/xen/, kernel/nsproxy.c, kernel/cgroup.c
Sistema completo de monitoreo y debugging que proporciona visibilidad profunda del funcionamiento del kernel y permite el diagnóstico de problemas en tiempo real.
Archivos: kernel/trace/, kernel/debug/, kernel/profiling/, kernel/bpf/
Sistema de descripción de hardware que permite al kernel descubrir y configurar automáticamente dispositivos de hardware sin necesidad de drivers específicos hardcodeados.
Archivos: drivers/of/, drivers/acpi/, drivers/firmware/
Subsistema gráfico que proporciona aceleración por hardware, soporte para múltiples monitores y capacidades multimedia avanzadas.
Archivos: drivers/gpu/drm/, drivers/media/, drivers/video/
Sistema de audio avanzado que proporciona soporte para múltiples formatos, procesamiento de audio en tiempo real y gestión de dispositivos de audio complejos.
Archivos: sound/core/, sound/soc/, sound/pci/, sound/usb/
Sistema unificado de entrada y salida que maneja todos los dispositivos de interfaz de usuario, desde teclados y ratones hasta pantallas táctiles y sensores.
Archivos: drivers/input/, drivers/hid/, drivers/iio/