- Maestro es un proyecto que busca crear desde cero en Rust un sistema operativo tipo Unix que sea lo bastante compatible con Linux como para poder usarse en el día a día, pero manteniéndose ligero
- Comenzó en 2018 como un proyecto escolar y al principio fue implementado en C, pero se cambió a Rust por problemas para gestionar la base de código y por los requisitos de seguridad en el desarrollo del kernel
- Actualmente es un kernel monolítico para x86 de 32 bits, y de 437 llamadas al sistema de Linux, 135 están implementadas en cierto grado, lo que equivale a alrededor del 31%
- También se están desarrollando el sistema de arranque y gestor de demonios Solfège, utilidades del sistema y el gestor de paquetes blimp; además, funcionan musl, bash y parte de GNU coreutils
- Sigue en una etapa muy temprana y es inestable; las pruebas se centran en QEMU, VMWare y VirtualBox, por lo que es más seguro no instalarlo en una máquina con datos importantes
Objetivos y punto de partida de Maestro
- Maestro es un sistema operativo tipo Unix escrito desde cero en Rust
- El objetivo es crear un sistema ligero y suficientemente compatible con Linux como para permitir un uso cotidiano
- Se inició con la idea de crear un entorno que permita entender el sistema de la A a la Z y personalizarlo de la forma deseada
Por qué se cambió de C a Rust
- El primer commit se hizo el 22 de diciembre de 2018 a las 03:18, y el proyecto comenzó como una tarea escolar
- La implementación inicial avanzó durante alrededor de un año y medio en C, pero se volvió difícil mantener limpia la base de código
- Ventajas obtenidas al reiniciar el proyecto en Rust
- Fue posible rediseñar el proyecto desde cero basándose en lo aprendido de errores anteriores
- Permitió probar cosas más nuevas que simplemente reescribir en C un kernel parecido a Linux
- Gracias al sistema de tipos de Rust, parte de la responsabilidad de la seguridad de memoria puede recaer en el compilador y no solo en el programador
En qué puntos Rust resultó ventajoso en el desarrollo del kernel
- Depurar el desarrollo de un kernel es mucho más complicado que en una aplicación común
- Es difícil encontrar documentación, y la propia implementación del BIOS puede tener fallas
- Durante el arranque, el kernel puede acceder a toda la memoria, así que puede escribir incluso en ubicaciones incorrectas como su propio código
- No se pueden usar herramientas como valgrind para rastrear fugas de memoria
- gdb puede usarse con QEMU y VMWare, pero el comportamiento del kernel puede variar según el emulador o la máquina virtual
- También hay entornos como VirtualBox que no soportan gdb, y el soporte de gdb en QEMU y VMWare tampoco está completo; a veces gdb incluso falla
- Para reducir este tipo de problemas, un lenguaje con seguridad de memoria también resulta ventajoso en el desarrollo de kernels
- Rust ayudó a incorporar varias salvaguardas en el kernel y es considerado la mejor decisión del proyecto
Estado actual de la implementación
- Actualmente, Maestro es un kernel monolítico y solo soporta la arquitectura x86 de 32 bits
- Estado de implementación al momento de escribir esto
- De las 437 llamadas al sistema de Linux, 135 están implementadas en cierto grado
- Tasa de implementación de llamadas al sistema: {p:31}
- Sumando todo el repositorio, hay 615 archivos y 48,800 líneas de código
- La cantidad de líneas fue calculada con el comando
cloc
- Componentes del sistema operativo además del kernel
- Solfège: sistema de arranque y gestor de demonios algo similar a systemd, pero más ligero
- maestro-utils: conjunto de comandos de utilidades del sistema
- blimp: gestor de paquetes
- Otros componentes también están publicados en GitHub
- Software de terceros cuyo funcionamiento fue confirmado
- Biblioteca estándar de C musl
-
bash
- Algunos comandos de GNU coreutils como
ls,cat,mkdir,rm,rmdir,uname,whoami - Como neofetch original no reconoce a Maestro, se necesita una versión parcheada de neofetch
- Algunos comandos de GNU coreutils como
Cómo probarlo directamente y sus limitaciones
- El sistema operativo sigue en una etapa muy temprana y es muy inestable
- No se recomienda instalarlo en una máquina con datos importantes
- Hasta ahora se ha probado principalmente en QEMU, VMWare y VirtualBox
- Hay dos formas de instalarlo
- Descargar un archivo
.isocomprimido ya compilado - Compilar la ISO manualmente
- Descargar un archivo
- La ISO incluye un instalador del sistema operativo y puede ejecutarse en QEMU, VMWare, VirtualBox, etc.
- Para ejecutar la ISO se necesita suficiente RAM, y 1GB es suficiente
- Esto se debe a que los paquetes a instalar se guardan en la RAM del initramfs y no en el disco
- Actualmente el sistema operativo no puede leer directamente memorias USB ni CD-ROM, así que depende del bootloader
Temas que tratará el artículo
- El objetivo no es escribir un tutorial para crear un sistema operativo
- Como recursos básicos sobre desarrollo de sistemas operativos, se recomiendan osdev.org y Philipp Oppermann’s blog
- En adelante se planea tratar temas más avanzados, procesos de resolución de problemas y la forma en que computadoras, sistemas operativos e internet funcionan por dentro
Dirección futura del desarrollo
- La prioridad es ordenar la base de código y optimizar el rendimiento
- Como comenzó como un proyecto escolar, hubo partes donde se tomaron atajos para cumplir plazos, y ahora hay que pagar esa deuda técnica acumulada
- También hay que corregir algunas fugas de memoria, y la optimización de rendimiento podría convertirse en tema de futuros artículos
- El siguiente gran objetivo es lograr que el gestor de paquetes funcione completamente sobre el sistema operativo
- Se necesita soporte de red, que actualmente está en desarrollo
- Se necesita soporte para bibliotecas compartidas
- Las bibliotecas compartidas requieren mapear archivos directamente en memoria, pero la implementación actual de la llamada al sistema
mmapdel kernel no lo permite
- Después de eso, será más fácil instalar y probar programas como gcc/g++, clang, rustc, make, Git y Vim
- El objetivo final es llegar a un flujo de desarrollo del kernel sobre el propio Maestro
Proceso de desarrollo para mejorar el grado de completitud del kernel
- El desarrollo avanza ejecutando programas sobre el kernel y, si no funcionan, identificando e implementando o corrigiendo la llamada al sistema que causa el problema
- Ejecutar el programa sobre el kernel
- Si no funciona, revisar la salida de llamadas al sistema para encontrar la primera que provoca el problema
- Si esa llamada al sistema no está implementada o tiene un bug, implementarla o corregirla
- Volver a ejecutar el programa
- Cuantos más programas funcionen correctamente sobre el kernel, más estable y completo será
1 comentarios
Opiniones en Hacker News
Muchísimas gracias por el apoyo; significa mucho, porque le he dedicado muchísimo esfuerzo a este proyecto.
Parece que ahora el sitio web está bastante lento o caído; hay más tráfico del esperado y también sospecho de un ataque DoS.
Ahora estoy en el trabajo, así que me cuesta concentrarme de inmediato, pero cuando llegue a casa intentaré arreglarlo para que funcione mejor.
En 2010, cuando Rust todavía no existía, poco después de graduarme de la universidad jugué un poco en C con un OS hobby tipo Unix, y fue muy divertido.
Me da envidia que hayas podido encontrar el tiempo para llegar hasta aquí.
La barra de navegación ocupa como el 33% de la pantalla y no se puede quitar.
No entiendo por qué la gente fija estas cosas y quita espacio valioso de lectura. Si uno quiere, puede desplazarse hasta arriba en unos 300 ms.
Es un proyecto pequeño y genial. Sorprende que arranque hasta este punto sin haber implementado ni un tercio de las llamadas al sistema de Linux.
Eso sí, es muy probable que lo que falta sea lo más complejo. Por ejemplo, la capa TTY ahora parece bastante básica, y hacerla bien probablemente implique mucho trabajo.
Por eso me cuesta esperar que Maestro ejecute aplicaciones de Linux en los próximos 3 años. Incluso sin considerar los miles de drivers que tiene Linux.
En las plataformas maduras se acumula lógica para soportar muchos escenarios, y por eso la mayoría no necesita la mayor parte del sistema completo.
Es parecido a la frase “nadie usa más del 10% de Excel, pero el 10% que usa cada persona es distinto”.
Si implementaras solo el 30% de las funciones de Excel, probablemente podrías crear un motor capaz de abrir el 99% de las hojas de cálculo del mundo. Pero si quieres compatibilidad documental completa, todavía queda mucho camino.
Algunas llamadas al sistema solo se invocan en ciertas rutas de código, o pueden ser llamadas nuevas que solo hacen falta cuando se apunta a un kernel más reciente.
Hay muchas llamadas al sistema, y varias son bastante oscuras. Si es una reimplementación completamente abierta, al final habrá que soportar la mayoría, pero un tercio es un buen comienzo.
[1] Quería ejecutar la VM en bare metal o arrancarla como VM, y salvo algo como
init=/path/to/the/vm, esto parecía la forma de llegar ahí con el menor esfuerzo. Pero ese enfoque no me da lo que realmente quiero: tener los drivers de hardware y la pila TCP dentro del lenguaje de la VM.No creo que tenga que ejecutar Steam, LibreOffice y Firefox para ser útil. Muchos componentes de servidores comunes o de arquitecturas de microservicios hacen cosas relativamente simples, y podrían beneficiarse bastante de un kernel seguro y simple.
También está Kerla, un kernel monolítico hecho en Rust que apuntaba a la compatibilidad con la ABI de Linux. Aunque parece que lleva varios años inactivo.
[1] https://news.ycombinator.com/item?id=28986229
Tiene diseño de microkernel y probablemente sea un poco más maduro. Como tiene licencia MIT, parece que también habría margen para compartir código.
Sería interesante hacer pruebas de seguridad, pentesting y fuzzing para ver “si solo por estar hecho en Rust, un hacker hábil puede encontrar algo”.
Estoy 100% seguro de que las pruebas de fuzzing o de penetración revelarían muchos problemas. Todavía no he tenido tiempo para dedicarle a eso.
Parece algo que ya se había intentado en el proyecto Kerla, que ahora está detenido.
Suena como un proyecto interesante. Pero creo que las desventajas de usar C y las dificultades del desarrollo de un OS están sobre todo en la depuración.
Al pasarse a Rust, ciertos tipos de errores de memoria habrán desaparecido, pero ¿depurar sigue siendo igual de doloroso? ¿O se redujo lo suficiente como para ser tolerable?
Depurar sigue siendo doloroso, pero mucho menos que antes.
Por ejemplo, no es muy probable que te olvides de usar un mutex, porque el compilador te lo marca como error.
Eso no significa que sea una solución mágica; problemas como los interbloqueos siguen existiendo. Sobre todo cuando hay interrupciones de por medio.
Por ejemplo, si bloqueas un mutex y ocurre una interrupción, el código que bloqueó ese mutex queda detenido hasta que termine la interrupción. Pero si el manejador de la interrupción intenta bloquear el mismo mutex, se produce un interbloqueo, y el sistema de tipos no puede ayudarte con eso.
La solución es desactivar el manejo de interrupciones mientras el mutex está bloqueado, pero el compilador no puede imponerlo.
Un poco tangencial, pero me gustó Gource, que el autor usó en el video de contribuciones.
No lo había visto antes, aunque hace unos años tuve la idea de hacer algo parecido. Parece que no hay ideas completamente nuevas.
Sobre todo con fines de aprendizaje, me encanta la idea de crear un kernel propio. Me da curiosidad qué recursos usaste para entender el kernel y los OS en general.
Me sorprende que no se haya mencionado Theseus OS. Es un OS en desarrollo escrito desde cero en Rust, que aprovecha las garantías de seguridad de memoria del compilador de Rust para ofrecer automáticamente muchas cosas que en un OS tradicional habría que cablear con mucho cuidado.
Por ejemplo, es seguro aunque tenga un único nivel de privilegio y una arquitectura de espacio de direcciones único. Todas las partes del OS son hot-pluggable.
La desventaja es que todo el código nativo debe ser Rust, pero el año pasado se implementó un runtime WASM. Hilo relacionado de hace 3 años:
https://news.ycombinator.com/item?id=25741729
No pensé que hubiera alguien tan loco como para hacerse cargo del proyecto ft_penguin. Todavía no sé si ese era el nombre correcto, pero sinceramente, excelente trabajo.
Cuando estaba en la escuela hace 7 años, pensaba que era uno de los proyectos con peor recompensa en relación con el tiempo necesario.
Me da curiosidad si al principio lo empezaste con un amigo y cómo era antes de reescribirlo en Rust. También me pregunto si hiciste otros proyectos al mismo tiempo.
Al ver el código recordé lo divertido que era, y ahora me dieron ganas de dejar mi trabajo en DevOps y dedicarme a embedded u otro trabajo de bajo nivel, que era lo que originalmente quería hacer.