Writing an OS in Rust

Philipp Oppermann's blog

Escribiendo un sistema operativo en Rust

Esta serie de blogs crea un pequeño sistema operativo en el lenguaje de programación Rust. Cada publicación es un pequeño tutorial e incluye todo el código necesario, para que puedas seguir los pasos si lo deseas. El código fuente también está disponible en el repositorio correspondiente de Github.

Última publicación: Async/Await

Un Binario Rust Autónomo

El primer paso para crear nuestro propio kernel de sistema operativo es crear un ejecutable en Rust que no enlace con la biblioteca estándar. Esto hace posible ejecutar código Rust directamente en el bare metal sin un sistema operativo subyacente.

leer más »

Un Kernel Mínimo en Rust

En esta publicación, crearemos un kernel mínimo de 64 bits en Rust para la arquitectura x86. Partiremos del un binario Rust autónomo de la publicación anterior para crear una imagen de disco arrancable que imprima algo en la pantalla.

leer más »

Modo de Texto VGA

El modo de texto VGA es una forma sencilla de imprimir texto en la pantalla. En esta publicación, creamos una interfaz que hace que su uso sea seguro y simple al encapsular toda la inseguridad en un módulo separado. También implementamos soporte para los macros de formato de Rust.

leer más »

Pruebas

Esta publicación explora las pruebas unitarias e integración en ejecutables no_std. Utilizaremos el soporte de Rust para marcos de prueba personalizados para ejecutar funciones de prueba dentro de nuestro núcleo. Para reportar los resultados fuera de QEMU, utilizaremos diferentes características de QEMU y la herramienta bootimage.

leer más »

Excepciones de CPU

Las excepciones de CPU ocurren en diversas situaciones erróneas, por ejemplo, al acceder a una dirección de memoria inválida o al dividir por cero. Para reaccionar ante ellas, tenemos que configurar una tabla de descriptores de interrupción (IDT, por sus siglas en inglés) que proporcione funciones manejadoras. Al final de esta publicación, nuestro núcleo será capaz de capturar excepciones de punto de interrupción y reanudar la ejecución normal después.

leer más »

Excepciones de Doble Fallo

Esta publicación explora en detalle la excepción de doble fallo, que ocurre cuando la CPU no logra invocar un controlador de excepciones. Al manejar esta excepción, evitamos fallos triples fatales que causan un reinicio del sistema. Para prevenir fallos triples en todos los casos, también configuramos una Tabla de Pila de Interrupciones (IST) para capturar dobles fallos en una pila de núcleo separada.

leer más »

Interrupciones de Hardware

En esta publicación, configuramos el controlador de interrupciones programable para redirigir correctamente las interrupciones de hardware a la CPU. Para manejar estas interrupciones, agregamos nuevas entradas a nuestra tabla de descriptores de interrupciones, tal como lo hicimos con nuestros manejadores de excepciones. Aprenderemos cómo obtener interrupciones de temporizador periódicas y cómo recibir entrada del teclado.

leer más »

Introducción a la Paginación

Esta publicación introduce la paginación (paging), un esquema de gestión de memoria muy común que también utilizaremos para nuestro sistema operativo. Explica por qué se necesita la aislamiento de memoria, cómo funciona la segmentación (segmentation), qué es la memoria virtual (virtual memory) y cómo la paginación soluciona los problemas de fragmentación de memoria. También explora el diseño de las tablas de páginas multinivel en la arquitectura x86_64.

leer más »

Implementación de Paginación

Esta publicación muestra cómo implementar soporte para paginación en nuestro núcleo. Primero explora diferentes técnicas para hacer accesibles los marcos de la tabla de páginas físicas al núcleo y discute sus respectivas ventajas y desventajas. Luego implementa una función de traducción de direcciones y una función para crear un nuevo mapeo.

leer más »

Asignación en el Heap

Este post añade soporte para la asignación en el heap a nuestro núcleo. Primero, proporciona una introducción a la memoria dinámica y muestra cómo el borrow checker (verificador de préstamos) previene errores comunes de asignación. Luego, implementa la interfaz básica de asignación de Rust, crea una región de memoria en el heap y configura una crate de asignador. Al final de este post, todos los tipos de asignación y recolección de la crate alloc integrada estarán disponibles para nuestro núcleo.

leer más »

Diseños de Allocadores

Este post explica cómo implementar allocadores de heap desde cero. Presenta y discute diferentes diseños de allocadores, incluyendo asignación de bump, asignación de lista enlazada y asignación de bloques de tamaño fijo. Para cada uno de los tres diseños, crearemos una implementación básica que se puede utilizar para nuestro kernel.

leer más »

Async/Aait

En esta publicación, exploramos el multitasking cooperativo y la característica async/await de Rust. Observamos en detalle cómo funciona async/await en Rust, incluyendo el diseño del trait Future, la transformación de máquina de estado y el pinning. Luego añadimos soporte básico para async/await a nuestro núcleo creando una tarea de teclado asíncrona y un ejecutor básico.

leer más »

Status Updates

These posts give a regular overview of the most important changes to the blog and the tools and libraries behind the scenes.

First Edition

You are currently viewing the second edition of “Writing an OS in Rust”. The first edition is very different in many aspects, for example it builds upon the GRUB bootloader instead of using the `bootloader` crate. In case you're interested in it, it is still available. Note that the first edition is no longer updated and might contain outdated information. read the first edition »

Apóyame

Crear y mantener este blog y las bibliotecas asociadas es mucho trabajo, pero realmente disfruto haciéndolo. Al apoyarme, me permites invertir más tiempo en nuevo contenido, nuevas características y mantenimiento continuo. La mejor manera de apoyarme es patrocinarme en GitHub. ¡Gracias!