📝 TEMA1_PARTE2
← Volver

TEMA 1 — CONCEPTOS DE SISTEMAS OPERATIVOS

Parte 2: E/S, Sistema de Archivos, Seguridad, Kernel, Interfaces, Arranque y Evolución

(Versión ampliada con detalle técnico y orientación a examen)


Nota de estudio: Esta parte cubre los mecanismos internos del SO que más aparecen en preguntas de examen prácticas: cómo gestiona el SO los dispositivos, qué son los drivers, cómo funciona el sistema de archivos (y qué diferencia hay entre ext4 y NTFS), cómo se implementa la seguridad a nivel de SO (permisos, sudo, autenticación), y cómo arranca el sistema. Conecta directamente con las preguntas 1 (comandos Linux), 2 (MFA), 9 (permisos NTFS) y 10 (redes del edificio) del examen de la Politécnica.


2.6 GESTIÓN DE ENTRADA/SALIDA (E/S)

La gestión de E/S es una de las partes más complejas del SO porque tiene que hacer de puente entre el mundo del software (rápido, uniforme, abstracto) y el hardware de los dispositivos (lento, heterogéneo, específico). Un disco NVMe y un teclado PS/2 son radicalmente distintos en hardware, pero el programador los usa con las mismas llamadas al sistema (open, read, write).

2.6.1 Clasificación de dispositivos de E/S

Dispositivos de bloque

Almacenan y transfieren datos en bloques de tamaño fijo (típicamente 512 bytes a 4 KB por sector). Permiten acceso aleatorio: se puede leer el bloque 10.000 sin haber leído los 9.999 anteriores.

El SO gestiona estos dispositivos con un buffer de bloques (block buffer cache): las lecturas se hacen en bloques completos aunque solo se necesite un byte, y se guardan en RAM para reutilizarlos. Esto es crucial para el rendimiento porque un disco HDD tarda ~10 ms en buscar un sector, independientemente de cuántos bytes se lean de él.

Ejemplos: discos duros HDD, SSDs (SATA, NVMe), unidades USB, tarjetas SD, CD/DVD.

Conexión interna: el sistema de archivos (ext4, NTFS, FAT32...) se construye sobre estos dispositivos de bloque. El SO ve el disco como una secuencia de bloques numerados; el sistema de archivos organiza esos bloques en ficheros y directorios.

Dispositivos de carácter

Transfieren datos carácter a carácter (byte a byte), de forma secuencial. No hay concepto de "bloque" ni de posición; los datos llegan en un flujo continuo sin estructura interna. No permiten acceso aleatorio.

Ejemplos: teclado, ratón, puerto serie (RS-232), terminales (TTY/PTY), interfaces de audio.

El SO gestiona estos dispositivos con colas de caracteres: los bytes que llegan del dispositivo se acumulan en una cola en el kernel hasta que el proceso los lee. Si el proceso no lee rápido, la cola puede desbordarse.

¿Por qué importa la distinción? Los algoritmos de planificación de disco (que optimizan el movimiento del cabezal) solo tienen sentido para dispositivos de bloque. Para dispositivos de carácter, se usan colas FIFO simples.

Dispositivos de red

Caso especial: no encajan bien en ninguna de las dos categorías anteriores. Transfieren datos en paquetes (datagramas) de tamaño variable con encabezados estructurados. El SO los gestiona a través de la pila de protocolos de red (TCP/IP), que es un subsistema propio del kernel.

Conexión con otros temas: la pregunta 6 del examen (cortafuegos) y la pregunta 5 (VPN) tratan de cómo el SO gestiona el tráfico de estos dispositivos de red a nivel de kernel (Netfilter en Linux, Windows Filtering Platform en Windows).


2.6.2 Drivers (controladores de dispositivo)

Un driver (controlador de dispositivo) es un módulo de software específico para un dispositivo hardware concreto, que implementa la interfaz estándar del SO usando los comandos propietarios del hardware.

Arquitectura en capas de la E/S

Aplicación (modo usuario)
    │  open("/dev/sda", ...)  read(fd, buf, n)  write(fd, buf, n)
    ▼
── Interfaz de llamadas al sistema ── (cambio a modo kernel)
    │
    ▼
Subsistema de E/S genérico del kernel
    │  (gestión de buffers, caché, planificación de disco, etc.)
    │
    ▼
Interfaz de driver de dispositivo
    │  (llamadas estándar: init, read, write, ioctl, release...)
    │
    ▼
Driver específico del dispositivo
    │  (código que entiende el hardware concreto:
    │   registros, comandos, interrupciones específicos)
    │
    ▼
Controladora hardware (p.ej.: controladora SATA, NVMe, USB...)
    │
    ▼
Dispositivo físico (disco, USB, teclado...)

¿Por qué en modo kernel? Los drivers necesitan acceder directamente a los registros de hardware (puertos I/O, memoria MMIO), gestionar interrupciones hardware y acceder a la RAM física. Todo esto requiere privilegios de modo kernel. La consecuencia es que un driver con un bug puede causar un kernel panic (pantalla azul en Windows). Por eso los SO modernos intentan aislar los drivers o validarlos (firma de drivers en Windows, módulos firmados en Linux para Secure Boot).

Tipos de drivers en Linux

En Linux, los dispositivos se exponen como ficheros especiales bajo el directorio /dev:
- Dispositivos de bloque: /dev/sda (primer disco SATA), /dev/nvme0n1 (primer disco NVMe), /dev/sdb1 (primera partición del segundo disco).
- Dispositivos de carácter: /dev/tty0 (terminal de consola), /dev/random (generador de números aleatorios), /dev/null (agujero negro: todo lo que se escribe se descarta), /dev/zero (genera ceros infinitos).

/dev/null y /dev/zero son dos de los dispositivos virtuales más usados en administración:
- cat fichero_grande > /dev/null → descarta la salida (útil para medir rendimiento sin escribir a disco).
- dd if=/dev/zero of=fichero bs=1M count=100 → crea un fichero de 100 MB relleno de ceros.

Carga dinámica de módulos en Linux

Linux tiene un kernel monolítico, pero los drivers pueden compilarse como módulos que se cargan y descargan en tiempo de ejecución sin reiniciar el sistema. Esto combina el rendimiento del kernel monolítico con la flexibilidad del microkernel.

Comandos para gestionar módulos:

lsmod              # Lista módulos cargados actualmente
modinfo e1000e     # Información sobre el módulo del driver Intel Ethernet
insmod driver.ko   # Carga un módulo manualmente
rmmod e1000e       # Descarga un módulo
modprobe e1000e    # Carga un módulo y sus dependencias automáticamente


2.6.3 Técnicas de E/S: cómo comunica la CPU con los dispositivos

E/S Programada (Polling o Busy-wait)

La CPU envía un comando al dispositivo y luego espera activamente mirando repetidamente un registro de estado del dispositivo hasta que la operación termina:

CPU: envía comando al dispositivo
CPU: while (dispositivo.estado != LISTO) { esperar; }  // bucle activo
CPU: lee/escribe datos
CPU: continúa con lo siguiente

Cuándo la CPU está en este bucle, no puede hacer nada más. Utilización de CPU = 100% pero la mayor parte del tiempo se desperdicia esperando.

¿Cuándo es aceptable? Solo para dispositivos extremadamente rápidos donde el tiempo de espera es menor que el overhead de configurar una interrupción. Ejemplo: algunos SSDs NVMe de alta velocidad o ciertos controladores de red en modo "busy polling" para latencias de microsegundos.

En la práctica: inaceptable para discos HDD (espera de ~10 ms) o incluso SSDs convencionales (~100 μs). Imagina que la CPU esperara 10 ms por cada lectura de disco: con 1000 lecturas por segundo, la CPU estaría el 100% del tiempo esperando.

E/S por Interrupciones

Es el modelo estándar y eficiente:

1. CPU: envía comando al dispositivo y registra un manejador de interrupción (ISR)
2. CPU: bloquea el proceso que pidió la E/S y ejecuta OTRO proceso (no se desperdicia tiempo)
3. [Tiempo después...] El dispositivo termina y genera una señal eléctrica: INTERRUPCIÓN HARDWARE
4. El procesador interrumpe lo que está haciendo y salta al vector de interrupciones
5. Se ejecuta la ISR (Interrupt Service Routine) del driver correspondiente
6. La ISR procesa los datos, desbloquea el proceso que esperaba y retorna
7. El planificador puede ahora asignar CPU al proceso desbloqueado

El controlador de interrupciones (PIC/APIC): el hardware tiene un chip (PIC: Programmable Interrupt Controller, o su versión moderna APIC: Advanced PIC) que gestiona las líneas de interrupción de todos los dispositivos y las prioriza antes de enviarlas al procesador.

Latencia de interrupción: el tiempo desde que el dispositivo genera la interrupción hasta que la ISR empieza a ejecutar. En sistemas normales: microsegundos. En RTOS (tiempo real): garantizado en nanosegundos a microsegundos.

¿Por qué no siempre es perfecta? Si hay muchas interrupciones por segundo (p.ej.: una tarjeta de red a 10 Gbps puede generar millones de interrupciones por segundo), el overhead de gestionar cada interrupción por separado puede consumir tanto tiempo de CPU que la comunicación efectiva se degrada. Solución: interrupt coalescing (agrupar varias interrupciones en una) o el modo polling selectivo de alta velocidad (NAPI en Linux para redes).

DMA (Direct Memory Access)

El problema que resuelve: con interrupciones, la transferencia de datos entre el dispositivo y la RAM la hace la CPU byte a byte (o palabra a palabra). Para un fichero de 1 GB, eso son miles de millones de ciclos de CPU solo copiando datos. La CPU debería estar libre para calcular, no para copiar.

La solución DMA: existe hardware especializado (el controlador DMA) que puede mover bloques de datos directamente entre el dispositivo y la RAM sin intervención de la CPU.

SIN DMA:
Disco → [lee dato] → CPU → [escribe dato] → RAM
        × millones de veces × (la CPU hace todo el trabajo)

CON DMA:
1. CPU al controlador DMA: "mueve N bytes desde el disco a la dirección X de RAM"
2. CPU queda libre para hacer otras cosas
3. Controlador DMA gestiona la transferencia directamente: Disco → DMA → RAM
4. Cuando termina: DMA genera UNA interrupción → "ya terminé"
5. CPU procesa el resultado

El problema de la coherencia de caché con DMA: el controlador DMA escribe directamente en RAM, pero la CPU puede tener esos datos en su caché L1/L2 con valores desactualizados. El SO debe gestionar esto mediante operaciones de flush/invalidación de caché antes y después de las transferencias DMA. Es uno de los aspectos más delicados de la programación de drivers.

Uso real: todas las transferencias de disco de alto rendimiento usan DMA. Los controladores NVMe tienen hasta 65.535 colas DMA simultáneas, permitiendo miles de operaciones de E/S concurrentes.


2.6.4 Buffering, Caching y Spooling

Estos tres mecanismos son técnicas del SO para mejorar el rendimiento de la E/S. Es importante no confundirlos.

Buffering

Un buffer es un área de memoria temporal que almacena datos en tránsito entre un origen y un destino que operan a velocidades diferentes.

¿Por qué es necesario? El disco escribe en bloques de 4 KB mínimo, pero un programa puede pedir escribir 1 byte. Si cada write(1 byte) causara una escritura a disco, el rendimiento sería desastroso. El SO acumula las escrituras en un buffer en RAM y las envía al disco cuando el buffer está lleno o se fuerza un flush (fsync()).

Doble buffer (double buffering): mientras el SO llena el buffer B1 con datos del proceso, simultáneamente envía el buffer B2 al dispositivo. Cuando B2 se vacía y B1 se llena, se intercambian. Esto permite solapamiento de procesamiento y transferencia.

Buffer de escritura diferida (write-back buffer): las escrituras se consideran completadas desde el punto de vista del proceso en cuanto los datos están en el buffer de RAM (aunque no hayan llegado al disco). Mejora mucho el rendimiento pero introduce riesgo: si hay un corte de luz antes de que el buffer se vacíe a disco, se pierden datos. Los sistemas de archivos con journaling (NTFS, ext4) mitigan este riesgo.

Conexión con el examen (pregunta 8c - recuperación ante desastres): El journaling protege contra pérdidas de datos causadas por el vaciado incompleto de buffers de escritura ante fallos del sistema.

Page Cache (Caché de páginas)

Es la caché de E/S más importante en Linux y Windows. El SO mantiene en RAM copias de los bloques de disco más recientemente accedidos. Cuando una aplicación lee un fichero, el SO primero mira si los datos están en la page cache; si están (cache hit), los devuelve directamente sin ir a disco; si no están (cache miss), los lee del disco y los guarda en la page cache para futuros accesos.

En Linux, la page cache puede ocupar toda la RAM libre disponible. El SO la reduce automáticamente cuando los procesos necesitan más RAM para sus datos. Esto es normal y deseable; RAM libre es RAM desperdiciada. Comandos como free -h muestran la RAM usada por la page cache en la columna "buff/cache".

Ejemplo de impacto: compilar un proyecto grande por primera vez tarda 60 segundos. La segunda vez tarda 5 segundos porque los ficheros fuente están en la page cache.

Spooling (Simultaneous Peripheral Operations Online)

El spooling resuelve el problema de que ciertos dispositivos (principalmente impresoras) son exclusivos y lentos: solo pueden procesar un trabajo a la vez y tardan mucho.

Sin spooling: si el proceso A está imprimiendo, el proceso B tiene que esperar bloqueado hasta que A termine. Inaceptable en un entorno multiusuario.

Con spooling: los trabajos de impresión no van directamente a la impresora sino a una cola de spooling en disco gestionada por un demonio (el spooler, como cupsd en Linux o el servicio Print Spooler en Windows). El spooler envía los trabajos a la impresora de uno en uno, en orden FIFO o según prioridades. Los procesos pueden "imprimir" instantáneamente (solo escriben en disco) y continúan sin bloquearse.

Proceso A ──► cola de spooling (disco) ──► spooler ──► Impresora
Proceso B ──►        (fichero 1)      │
Proceso C ──►        (fichero 2)      │ Los envía secuencialmente
              (fichero 3)             │

¿Dónde se aplica más allá de las impresoras? En cualquier recurso exclusivo y lento: colas de trabajo en sistemas batch, colas de email (el MTA como Postfix usa spooling), colas de mensajes en sistemas empresariales.


2.7 GESTIÓN DEL SISTEMA DE ARCHIVOS

El sistema de archivos es la forma en que el SO organiza y gestiona los datos almacenados en los dispositivos de almacenamiento. Sin él, el disco no sería más que una secuencia de bloques numerados sin estructura ni significado.

2.7.1 Conceptos fundamentales

Archivo

Un archivo (fichero) es la unidad lógica de almacenamiento: una colección nombrada de información relacionada que el SO trata como una unidad. Para el SO, un fichero es simplemente una secuencia de bytes almacenada en disco con metadatos asociados.

Tipos de ficheros en Linux (el tipo se indica con el primer carácter de ls -l):

Tipo Símbolo Descripción
Regular - Fichero de datos normal (texto, binario, ejecutable...)
Directorio d Contiene entradas que apuntan a otros ficheros/directorios
Enlace simbólico l Puntero a otro fichero (como un acceso directo)
Dispositivo de bloque b Representa un dispositivo de bloque (/dev/sda)
Dispositivo de carácter c Representa un dispositivo de carácter (/dev/tty0)
Pipe con nombre (FIFO) p Canal IPC con nombre en el sistema de ficheros
Socket s Socket de dominio Unix para IPC local

Filosofía Unix "todo es un fichero": en Unix/Linux, prácticamente todo se representa como un fichero en el sistema de ficheros. Los dispositivos son ficheros en /dev. Los procesos tienen sus atributos accesibles como ficheros en /proc (p.ej. /proc/1234/status muestra el estado del proceso 1234). La configuración del kernel en tiempo real se expone en /sys. Esto simplifica enormemente la programación: las mismas operaciones (open, read, write, close) sirven para ficheros normales, dispositivos, procesos y sockets.

Directorio y árbol de directorios

Un directorio es una tabla que asocia nombres de ficheros con sus inodos (o descriptores equivalentes). El directorio no contiene los datos del fichero, solo el nombre y un puntero a dónde están sus metadatos.

Estructura jerárquica: todos los sistemas de archivos modernos organizan los ficheros en una jerarquía de árbol. En Linux/Unix, hay un único árbol con raíz en /. En Windows, cada volumen tiene su propio árbol (C:\, D:\...).

Rutas absolutas vs relativas:
- Ruta absoluta: empieza en la raíz y especifica la ubicación completa. Ejemplo: /home/usuario/documentos/informe.txt en Linux, C:\Users\usuario\Documents\informe.txt en Windows.
- Ruta relativa: relativa al directorio de trabajo actual. Ejemplo: si estás en /home/usuario, la ruta relativa documentos/informe.txt equivale a la absoluta anterior.

Conexión directa con el examen (pregunta 1.a): el comando pwd (Print Working Directory) muestra la ruta absoluta del directorio de trabajo actual. Es la respuesta a "¿dónde estoy en el árbol de directorios ahora mismo?". Internamente realiza la llamada al sistema getcwd().

Inodo (i-node)

El inodo es la estructura de datos central de los sistemas de archivos Unix/Linux (ext4, XFS, Btrfs...). Cada fichero tiene exactamente un inodo que contiene:

Lo que NO está en el inodo: el nombre del fichero. El nombre está en el directorio que contiene el fichero. Por eso un mismo fichero puede tener múltiples nombres (enlaces duros): hay múltiples entradas en uno o varios directorios apuntando al mismo número de inodo.

Directorio /home/usuario/:
┌──────────────────┬──────────┐
│ Nombre           │ N° inodo │
├──────────────────┼──────────┤
│ informe.txt      │  12345   │
│ informe_copia.txt│  12345   │  ← mismo inodo: enlace duro
│ script.sh        │  67890   │
└──────────────────┴──────────┘

Inodo 12345:
├── tipo: fichero regular
├── tamaño: 45678 bytes
├── propietario: uid=1000 (usuario)
├── grupo: gid=1000
├── permisos: rw-r--r-- (644)
├── mtime: 2025-06-09 10:30:00
├── enlaces: 2 (informe.txt e informe_copia.txt)
└── bloques: [4521, 4522, 4523, ...]

Limitación importante: el número de inodos de un sistema de archivos es fijo al crearlo. Puedes quedarte sin inodos aunque tengas espacio en disco libre si has creado demasiados ficheros pequeños. Comprobable con df -i.


2.7.2 Principales sistemas de archivos

FAT32 (File Allocation Table 32)

Desarrollado por Microsoft en 1977 (FAT original) y extendido a FAT32 en 1996. Extremadamente simple.

Estructura: una tabla (FAT) donde cada entrada corresponde a un clúster del disco e indica si está libre, defectuoso, el número del siguiente clúster del fichero, o que es el último clúster.

Características:
- Sin permisos de acceso (cualquiera puede leer cualquier fichero).
- Sin journaling (vulnerable a corrupción por apagados bruscos).
- Tamaño máximo de fichero: 4 GB (limitación del campo de 32 bits para el tamaño).
- Tamaño máximo de partición: 2 TB.
- Compatible con prácticamente todos los sistemas operativos y dispositivos.

¿Cuándo usarlo? Únicamente cuando la compatibilidad universal es lo prioritario: pendrives que se van a usar en Windows, macOS, Linux, TVs, coches, etc. Para cualquier uso serio, usar exFAT o NTFS.

exFAT (Extended FAT)

Microsoft diseñó exFAT en 2006 como sucesor de FAT32 para dispositivos de almacenamiento flash grandes.

NTFS (New Technology File System)

El sistema de archivos de Windows desde Windows NT 3.1 (1993). Es el sistema de archivos de producción estándar para Windows.

Características técnicas clave:

Conexión directa con el examen (pregunta 9): toda la pregunta 9 trata específicamente de los permisos NTFS. Es fundamental entender los tipos de permisos (lectura, escritura, ejecución, control total, etc.), la diferencia entre permisos explícitos e heredados, y la diferencia entre permisos NTFS y permisos de uso compartido (Sharing).

ext4 (Fourth Extended Filesystem)

El sistema de archivos de Linux más extendido. Sucesor de ext3 (2001) y ext2 (1993).

Características técnicas:

Btrfs (B-tree Filesystem)

Sistema de archivos moderno de Linux, diseñado para ser el sucesor de ext4. Usado por defecto en Fedora (desde F33) y openSUSE.

Características avanzadas:
- Copy-on-Write (CoW): cuando se modifica un bloque, no se sobreescribe directamente. Se escribe en un nuevo lugar, y luego se actualizan los punteros. El bloque original permanece hasta que se libera. Garantiza que nunca hay estados intermedios inconsistentes en disco.
- Snapshots instantáneos: gracias al CoW, crear un snapshot (foto del estado del sistema de archivos) es casi instantáneo y ocupa prácticamente cero espacio adicional (solo se guardan los bloques que cambian después).
- Checksums de datos e metadatos: detecta silenciosamente la corrupción de datos (bitrot), que ocurre cuando un bloque del disco cambia sin que ninguna operación de escritura lo haya tocado (problema real en discos y NAND flash envejecidos).
- RAID integrado: gestiona conjuntos de discos (RAID 0, 1, 10, 5, 6) sin necesidad de software RAID adicional.
- Subvolúmenes: particiones lógicas dentro del mismo sistema de archivos que comparten el espacio libre.

ZFS

Desarrollado por Sun Microsystems para Solaris, ahora disponible en Linux (OpenZFS). Considerado por muchos el sistema de archivos más avanzado y robusto disponible.

Características:
- Integridad total de datos: checksum SHA-256 en cada bloque de datos y metadatos. Detecta y (con redundancia) corrige silenciosamente cualquier corrupción.
- RAID-Z (1, 2, 3): equivalente a RAID 5, 6, 7 pero sin el "write hole" que tienen los RAID convencionales.
- Desduplicación inline: detecta bloques idénticos y almacena solo una copia.
- Gestión de pool de almacenamiento: los discos se añaden a un pool y ZFS gestiona el espacio automáticamente.

Tabla comparativa rápida para el examen

Sistema SO Journaling Permisos Máx fichero Caso de uso
FAT32 Universal No No 4 GB Pendrives, compatibilidad
exFAT Universal No No 128 PB Tarjetas SD, discos externos
NTFS Windows ACL 16 EB Windows (sistema y datos)
ext4 Linux Unix rwx + ACL 16 TB Linux (sistema y datos)
XFS Linux Unix rwx + ACL 8 EB Servidores, ficheros grandes
Btrfs Linux CoW Unix rwx + ACL 16 EB Linux moderno, snapshots
ZFS Unix/Linux CoW 16 EB Almacenamiento crítico, NAS
APFS macOS/iOS CoW Apple (sistema y datos)

2.7.3 Journaling en profundidad

El journaling es tan importante que merece análisis detallado, dado que aparece en las preguntas de sistemas de archivos y recuperación ante desastres.

El problema que resuelve: actualizar un fichero en disco puede requerir modificar múltiples estructuras: el bloque de datos, el inodo (tamaño, timestamps), el bitmap de bloques libres, quizás entradas de directorio. Si el sistema falla a mitad de estas modificaciones, el sistema de archivos queda en un estado inconsistente: por ejemplo, el inodo dice que el fichero tiene 1000 bytes pero los bloques de datos solo tienen 500. Sin journaling, la recuperación requiere fsck (file system check), que escanea TODO el disco buscando inconsistencias. En un disco de varios TB, esto puede tardar horas.

La solución: antes de realizar las modificaciones reales, el SO escribe la operación completa en el journal como una transacción atómica:

1. [Journal] Escribir: "voy a modificar inodo 12345, bloque 4521, bitmap..."
2. [Journal] Marcar la transacción como "comprometida" (committed)
3. [Disco real] Realizar las modificaciones reales
4. [Journal] Marcar la transacción como "completada" (checkpointed)

Si el sistema falla entre los pasos 1 y 4: al reiniciar, el SO ve que hay transacciones comprometidas pero no completadas en el journal, y las rehace. Si falla antes del paso 2: la transacción incompleta en el journal se descarta. En ambos casos, el sistema de archivos queda consistente en segundos, sin necesidad de escanear todo el disco.

Modos de journaling en ext4:
- data=writeback: solo se registran los cambios de metadatos (inodos, directorios) en el journal. Los datos del fichero se escriben directamente. Más rápido pero los datos pueden ser inconsistentes (aunque los metadatos no lo sean).
- data=ordered (por defecto): los datos se escriben al disco ANTES de que los metadatos se registren en el journal. Garantiza que si el journal dice "el fichero tiene N bytes", esos N bytes están realmente en disco. Buena combinación de rendimiento y seguridad.
- data=journal: tanto datos como metadatos pasan por el journal. Máxima seguridad pero doble escritura → más lento.


2.7.4 Permisos en Linux (rwx): análisis completo

Los permisos en Linux son la implementación del modelo DAC (Discretionary Access Control) a nivel de sistema de archivos.

El modelo de permisos Unix

Cada fichero o directorio tiene exactamente tres entidades con permisos asociados:
1. Propietario (user/owner): el usuario que creó el fichero o al que se le asignó con chown.
2. Grupo (group): un grupo de usuarios. El propietario (o root) asigna un grupo al fichero con chgrp.
3. Otros (others): todos los demás usuarios que no son ni el propietario ni miembros del grupo.

Para cada entidad hay tres permisos:
- r (read / 4): leer.
- w (write / 2): escribir/modificar.
- x (execute / 1): ejecutar (si es fichero) / entrar al directorio (si es directorio).

ls -la /etc/passwd
-rw-r--r-- 1 root root 2847 Jun 9 2025 /etc/passwd
│└─┘└─┘└─┘
│ │  │  └── Otros: r-- = solo lectura (4)
│ │  └───── Grupo "root": r-- = solo lectura (4)  
│ └──────── Propietario "root": rw- = lectura y escritura (6)
└────────── Tipo: - (fichero regular)

Permisos en octal: propietario=6 (r+w), grupo=4 (r), otros=4 (r) → 644

Permisos sobre directorios: matiz importante

Los permisos tienen significado diferente en directorios:
- r (read): permite listar el contenido del directorio (ls). Sin r, no puedes ver qué hay dentro, aunque puedas entrar.
- w (write): permite crear, eliminar o renombrar ficheros dentro del directorio. Importante: para borrar un fichero no necesitas permisos sobre el fichero en sí, sino permiso w sobre el directorio que lo contiene.
- x (execute): permite "atravesar" el directorio (entrar en él con cd o acceder a ficheros dentro). Sin x, no puedes acceder a ningún fichero dentro aunque sepas su nombre.

Ejemplo práctico confuso: si tienes r pero no x en un directorio, puedes ver los nombres de los ficheros (ls) pero no acceder a ninguno. Si tienes x pero no r, puedes acceder a ficheros si sabes su nombre exacto, pero no listarlos.

Notación numérica octal

Cada grupo de tres permisos (rwx) se representa como un número de 0 a 7:

Octal Binario Permisos
0 000 ---
1 001 --x
2 010 -w-
3 011 -wx
4 100 r--
5 101 r-x
6 110 rw-
7 111 rwx

Permisos más comunes:
- 755 (rwxr-xr-x): el propietario puede todo; grupo y otros pueden leer y ejecutar. Típico para ejecutables y directorios accesibles públicamente.
- 644 (rw-r--r--): el propietario puede leer y escribir; grupo y otros solo leer. Típico para ficheros de configuración y documentos.
- 700 (rwx------): solo el propietario puede hacer todo. Típico para scripts privados.
- 600 (rw-------): solo el propietario puede leer y escribir. Típico para claves privadas SSH (~/.ssh/id_rsa).
- 777 (rwxrwxrwx): todos pueden hacer todo. Evitar en producción; peligroso.

El comando chmod en detalle

# Notación numérica (octal):
chmod 755 script.sh        # rwxr-xr-x
chmod 644 fichero.txt      # rw-r--r--
chmod 700 clave_privada    # rwx------
chmod -R 755 /directorio   # Aplica recursivamente a todo el directorio

# Notación simbólica:
chmod u+x script.sh        # Añade ejecución al propietario (user)
chmod g-w fichero.txt      # Quita escritura al grupo
chmod o=r fichero.txt      # Establece exactamente r-- para otros
chmod a+r fichero.txt      # Añade lectura para todos (all: u+g+o)
chmod u=rwx,g=rx,o=r f.sh  # Establece permisos exactos para cada entidad

Permisos especiales: SUID, SGID y Sticky Bit

Además de los 9 bits rwx habituales, existen 3 bits especiales:

SUID (Set User ID — bit 4000):
Cuando se activa en un ejecutable, el programa se ejecuta con los privilegios del propietario del fichero, no del usuario que lo ejecuta.

Ejemplo fundamental: /usr/bin/sudo y /usr/bin/passwd tienen SUID activado y son propiedad de root. Cuando un usuario normal ejecuta sudo o passwd, ese proceso corre temporalmente con privilegios de root, aunque el usuario no sea root. El programa es responsable de validar que el usuario tiene permiso (consultando /etc/sudoers).

ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 232416 /usr/bin/sudo
    ^ la 's' en lugar de 'x' indica SUID activado

Relevancia directa con el examen (pregunta 1.b — sudo): este es exactamente el mecanismo que hace funcionar sudo. Es una aplicación del SUID a nivel de SO.

Vulnerabilidad de seguridad: si un programa con SUID tiene un bug explotable (buffer overflow, etc.), un atacante puede abusar de él para escalar privilegios a root. Por eso NTFS y muchos entornos de seguridad prohíben o monitorizan los ficheros SUID.

SGID (Set Group ID — bit 2000):
En un ejecutable: similar a SUID pero el proceso toma el grupo del fichero.
En un directorio: los nuevos ficheros creados dentro del directorio heredan el grupo del directorio (no el grupo principal del creador). Muy útil para directorios compartidos de equipo.

Sticky Bit (bit 1000):
En un directorio: solo el propietario de un fichero (o root) puede borrarlo o renombrarlo, aunque otros tengan permiso de escritura en el directorio. Protege los ficheros de otros usuarios.

Ejemplo clásico: /tmp tiene sticky bit activado (los permisos se muestran como rwxrwxrwt). Cualquier usuario puede crear ficheros en /tmp, pero no puede borrar los ficheros de otros usuarios.

ls -ld /tmp
drwxrwxrwt 10 root root 4096 Jun 9 2025 /tmp
         ^ 't' indica sticky bit activado

2.8 GESTIÓN DE SEGURIDAD

La seguridad del SO es el conjunto de mecanismos que controlan quién puede hacer qué en el sistema. Se organiza en tres pilares: autenticación, autorización y auditoría (los tres pilares de la seguridad de acceso, a veces llamados AAA).

2.8.1 Autenticación: verificar la identidad

La autenticación es el proceso de verificar que el usuario es quien dice ser. Los métodos se clasifican en tres factores:

Factor 1: "Algo que sabes" (conocimiento)

Contraseñas: el método más antiguo y extendido. Una contraseña es un secreto compartido entre el usuario y el sistema.

¿Cómo almacena el SO las contraseñas? Nunca en texto plano. El SO almacena el hash de la contraseña. Cuando el usuario introduce su contraseña, el SO calcula su hash y lo compara con el almacenado. Si el hash coincide, la contraseña es correcta.

Limitaciones de las contraseñas:
- Pueden ser adivinadas (fuerza bruta, diccionario).
- Pueden ser robadas (phishing, keyloggers, brechas de datos).
- Los usuarios eligen contraseñas débiles o las reutilizan.

PINs: en Windows Hello, el PIN es local al dispositivo (no se envía por red) y está protegido por el TPM del equipo. Es más seguro de lo que parece aunque sea más corto que una contraseña.

Factor 2: "Algo que tienes" (posesión)

Tokens físicos (hardware tokens): dispositivos como YubiKey que generan códigos OTP (One-Time Password) o realizan operaciones criptográficas de firma. Muy seguros porque el secreto nunca sale del dispositivo.

TOTP (Time-Based One-Time Password) — RFC 6238:
Es el estándar detrás de las aplicaciones de autenticación como Google Authenticator, Microsoft Authenticator, o Authy.

¿Cómo funciona técnicamente?
1. Durante el registro, el servidor genera un secreto compartido (clave HMAC, típicamente 20 bytes aleatorios).
2. Este secreto se comparte con el cliente de forma segura (habitualmente mediante un código QR).
3. Para generar un código OTP: TOTP = HMAC-SHA1(secreto, floor(tiempo_unix / 30)). El tiempo Unix dividido por 30 da un contador que cambia cada 30 segundos.
4. El resultado se trunka a 6 dígitos.
5. El servidor realiza el mismo cálculo y compara. Acepta también el código del intervalo anterior y siguiente para compensar pequeñas desincronizaciones de reloj.

Ventajas del TOTP: el código cambia cada 30 segundos, por lo que incluso si alguien intercepta un código ya utilizado, no puede reutilizarlo. No requiere conexión a Internet (el cálculo es local). Sin embargo, es vulnerable a ataques de phishing en tiempo real (el atacante puede solicitar el código al usuario y usarlo inmediatamente antes de que expire).

Tarjetas inteligentes (smart cards): contienen un chip que almacena certificados digitales. La autenticación se realiza mediante criptografía de clave pública: el sistema reta al usuario a firmar un desafío con su clave privada (que nunca sale de la tarjeta). Usadas en DNI electrónico, acceso a entornos corporativos de alta seguridad.

Factor 3: "Algo que eres" (inherencia / biometría)

Huella dactilar: el sensor captura la imagen de la huella, extrae características (minutiae: bifurcaciones y terminaciones de las crestas) y las compara con el perfil almacenado. Nunca se almacena la imagen cruda, sino el vector de características.

Reconocimiento facial: en Windows Hello, el sensor infrarrojo 3D captura la geometría del rostro para evitar ataques con fotografías.

Iris: muy alta precisión y dificultad de falsificación. Usado en sistemas de alta seguridad.

Limitaciones de la biometría:
- No se puede "cambiar" si se compromete (no puedes cambiar tu huella dactilar como cambias una contraseña).
- Puede tener falsos positivos (FRR/FAR: False Rejection Rate / False Acceptance Rate).
- Privacidad: los datos biométricos son especialmente sensibles.

MFA (Multi-Factor Authentication)

La autenticación multifactor combina dos o más factores de categorías diferentes. Si un factor se compromete (p.ej. roban tu contraseña), el atacante aún necesita el segundo factor (tu teléfono con la app TOTP) para acceder.

Conexión directa con el examen (pregunta 2): La pregunta 2 del examen pide analizar tres opciones de MFA. Usando los conceptos anteriores:
- Opción a (segunda contraseña): no es realmente MFA si ambas contraseñas son del mismo factor "algo que sabes". No añade protección real si el atacante puede obtener ambas por el mismo vector (phishing, brecha de datos).
- Opción b (TOTP): combina "algo que sabes" (contraseña) con "algo que tienes" (teléfono con app TOTP). MFA real y efectiva.
- Opción c (biometría + dispositivo específico): combina "algo que eres" (huella) con "algo que tienes" (portátil autorizado). MFA real, pero eliminar la contraseña reduce la resistencia a ciertos ataques.


2.8.2 Autorización: controlar el acceso

Una vez que el SO sabe quién es el usuario, debe determinar qué puede hacer. Los modelos principales:

DAC (Discretionary Access Control)

El propietario del recurso tiene discreción para decidir quién puede acceder. Es el modelo de Unix/Linux (permisos rwx) y Windows NTFS (ACLs).

En Unix/Linux: el propietario del fichero establece los permisos con chmod y chown. El SO verifica los permisos al intentar acceder.

En Windows NTFS: cada objeto (fichero, directorio, clave de registro, impresora...) tiene una ACL (Access Control List) que es una lista de ACEs (Access Control Entries). Cada ACE especifica un usuario o grupo y qué permisos tiene (leer, escribir, ejecutar, borrar, cambiar permisos, tomar posesión...) y si son permisos "allow" o "deny". Los "deny" tienen precedencia sobre los "allow".

Limitación del DAC: si el usuario propietario comete un error de configuración (da permisos a quien no debe) o un proceso del usuario se ve comprometido por malware, el malware tiene todos los permisos del usuario. El DAC no protege contra usuarios descuidados o procesos comprometidos.

MAC (Mandatory Access Control)

El sistema (no el usuario) impone reglas de acceso basadas en etiquetas de seguridad asignadas tanto a los sujetos (usuarios, procesos) como a los objetos (ficheros, sockets). Los usuarios no pueden cambiar estas reglas.

SELinux (Security-Enhanced Linux): desarrollado por la NSA, integrado en el kernel Linux. Cada proceso tiene un contexto de seguridad (dominio) y cada recurso tiene un contexto. Las reglas SELinux definen qué dominios pueden acceder a qué contextos.

Por ejemplo, aunque el servidor web Apache se ejecute como root (hipotético), SELinux puede impedir que acceda a cualquier directorio excepto /var/www/html. Si Apache es comprometido, el atacante no puede acceder a /etc/shadow aunque técnicamente tenga UID=0, porque SELinux lo bloquea.

AppArmor: alternativa a SELinux, más sencilla de configurar. Usa perfiles por aplicación que describen a qué rutas del sistema de archivos puede acceder. Usado por defecto en Ubuntu.

RBAC (Role-Based Access Control)

Los permisos no se asignan directamente a usuarios sino a roles, y los usuarios se asignan a roles. Esto simplifica la administración: para añadir un nuevo administrador, solo se le asigna el rol "Administrador"; no hace falta revisar y copiar los permisos de otro administrador manualmente.

Active Directory (Windows): implementación empresarial de RBAC. Los administradores crean grupos (que actúan como roles), asignan permisos a los grupos, y añaden usuarios a los grupos. Las GPO (Group Policy Objects) definen políticas de seguridad que se aplican automáticamente a usuarios y equipos según su pertenencia a grupos y unidades organizativas (OU).


2.8.3 Auditoría: registrar y detectar

La auditoría es el registro de eventos relevantes de seguridad para detectar intrusiones, investigar incidentes y demostrar cumplimiento normativo.

En Linux:
- /var/log/auth.log (Debian/Ubuntu) o /var/log/secure (RHEL/CentOS): todos los intentos de autenticación (exitosos y fallidos), usos de sudo, inicios de sesión SSH.
- journald (journalctl): log centralizado del sistema (systemd). Almacena logs de todos los servicios del sistema.
- auditd: subsistema de auditoría del kernel Linux. Puede registrar cualquier llamada al sistema: qué proceso ejecutó qué syscall con qué argumentos y resultado. Nivel de detalle máximo para entornos de alta seguridad.

En Windows:
- Visor de eventos (eventvwr.msc): interfaz gráfica para ver los logs del sistema.
- Categorías de log: Security (intentos de login, cambios de permisos), System (eventos del SO), Application (eventos de aplicaciones).
- Los eventos de seguridad tienen IDs estándar: 4624 (login exitoso), 4625 (login fallido), 4688 (nuevo proceso creado), 4732 (usuario añadido a grupo privilegiado).

Relevancia para el examen: sudo (pregunta 1.b) cada vez que se usa, genera una entrada en /var/log/auth.log con el usuario que lo ejecutó, el comando que usó, y si fue exitoso o denegado. Esto es auditoría en acción.


3. ESTRUCTURA INTERNA DEL SO: EL KERNEL

3.1 Modo usuario vs modo kernel

Esta es quizás la distinción más fundamental de la arquitectura de cualquier SO moderno. El procesador opera en (al menos) dos modos de privilegio:

Modo usuario (User Mode / Ring 3)

Nivel de privilegios restringido. Todos los programas de usuario (navegador, editor de texto, servidor web...) ejecutan en modo usuario.

Restricciones del modo usuario:
- No puede ejecutar instrucciones privilegiadas (modificar registros de control de la CPU, gestionar interrupciones hardware...).
- No puede acceder directamente al hardware (puertos I/O, registros de dispositivos).
- Solo puede acceder a su propio espacio de memoria virtual.
- Cualquier intento de violar estas restricciones causa una excepción de protección: el hardware transfiere el control al kernel, que normalmente termina el proceso infractor con una señal (SIGSEGV: segmentation fault).

Consecuencia: un bug en una aplicación de usuario, por grave que sea, solo puede dañar ese proceso. No puede dañar otros procesos ni el SO.

Modo kernel (Kernel Mode / Ring 0)

Nivel de privilegios máximo. El kernel del SO ejecuta en modo kernel.

Capacidades del modo kernel:
- Puede ejecutar cualquier instrucción del procesador, incluyendo las privilegiadas.
- Puede acceder a cualquier dirección de memoria (incluyendo la memoria de cualquier proceso).
- Puede configurar la MMU, gestionar interrupciones, acceder a registros de hardware.
- En x86, también existen los anillos Ring 1 y Ring 2 (para hypervisores y drivers en algunos modelos), pero en la práctica la mayoría de SO usan solo Ring 0 y Ring 3.

Consecuencia: un bug en código que corre en modo kernel puede tumbar todo el sistema. Un driver con un buffer overflow puede causar un kernel panic (Linux) o pantalla azul BSOD (Windows). Por eso el código del kernel está escrito con extremo cuidado y los drivers deben ser validados.


3.2 Llamadas al sistema (System Calls): la puerta al kernel

Las llamadas al sistema (syscalls) son el mecanismo que permite a los procesos en modo usuario solicitar servicios del kernel. Son la única forma de cruzar la frontera modo usuario → modo kernel de forma controlada.

Mecanismo detallado

Aplicación en modo usuario:
    printf("Hola\n");           // función de librería estándar
        │
        │ La libc implementa printf usando write()
        ▼
    write(1, "Hola\n", 5);     // wrapper de syscall en la librería libc
        │
        │ La libc coloca el número de syscall (4 en x86 = write)
        │ y los argumentos en registros de CPU (eax, ebx, ecx, edx)
        ▼
    INSTRUCCIÓN SYSCALL         // en x86-64 la instrucción se llama "syscall"
    (o INT 0x80 en x86 antiguo) // o "sysenter" según la arquitectura
        │
        │ El hardware:
        │ 1. Guarda el puntero de instrucción actual (para poder volver)
        │ 2. Cambia a modo kernel (Ring 0)
        │ 3. Salta a la dirección del manejador de syscalls del kernel
        ▼
Kernel en modo kernel:
    manejador_syscalls():
        │ Lee el número de syscall de eax
        │ Busca en la tabla de syscalls: sys_write()
        ▼
    sys_write():
        │ Verifica que fd=1 es un descriptor válido para este proceso
        │ Verifica que el buffer "Hola\n" está en memoria accesible
        │ Escribe los bytes al dispositivo correspondiente a fd=1 (stdout)
        │ Coloca el valor de retorno (5 = bytes escritos) en eax
        ▼
    RETORNO DE SYSCALL (sysret / iret)
        │ El hardware:
        │ 1. Cambia de vuelta a modo usuario (Ring 3)
        │ 2. Restaura el puntero de instrucción (vuelve a donde estaba)
        ▼
Aplicación en modo usuario:
    // write() retorna 5
    // printf continúa

Tabla de syscalls importantes

Syscall Número (Linux x86-64) Descripción
read 0 Lee datos de un descriptor de fichero
write 1 Escribe datos a un descriptor de fichero
open 2 Abre un fichero; devuelve un fd
close 3 Cierra un descriptor de fichero
stat 4 Obtiene metadatos de un fichero (inodo)
mmap 9 Mapea memoria (fichero o anónima) en el espacio de proceso
fork 57 Crea un proceso hijo copia del padre
execve 59 Reemplaza el proceso actual con un nuevo programa
exit 60 Termina el proceso actual
kill 62 Envía una señal a un proceso
getpid 39 Devuelve el PID del proceso actual
chmod 90 Cambia los permisos de un fichero
chown 92 Cambia propietario y grupo de un fichero
getcwd 79 Devuelve la ruta del directorio de trabajo actual

Conexión directa con los comandos del examen:
- pwd → internamente llama a getcwd (syscall 79).
- touch fichero → si el fichero no existe, llama a open(path, O_CREAT|O_WRONLY, 0666) (syscall 2). Si existe, llama a utimensat para actualizar timestamps.
- chmod 755 f → llama a chmod(path, 0755) (syscall 90).
- kill 1234 → llama a kill(1234, SIGTERM) (syscall 62).
- sudo cmd → es un ejecutable con SUID que llama a múltiples syscalls para verificar /etc/sudoers, autenticar al usuario y ejecutar el comando con setuid(0) + execve.


3.3 Arquitecturas del kernel: análisis comparativo

Kernel Monolítico

Todo el código del SO (gestión de procesos, memoria, sistema de archivos, drivers, red, IPC...) reside en un único bloque binario que ejecuta completamente en modo kernel. No hay separación entre subsistemas: la función de gestión de procesos puede llamar directamente a la función del sistema de archivos.

┌────────────────────────────────────────────────────────┐  Modo kernel
│                 KERNEL MONOLÍTICO                       │
│                                                         │
│  Planificador │ Memoria │ VFS │ Drivers │ Red │ IPC    │
│       │            │       │       │        │     │    │
│       └────────────┴───────┴───────┴────────┴─────┘    │
│              Comunicación directa (llamadas internas)   │
└────────────────────────────────────────────────────────┘
                        Hardware

Ventaja principal: rendimiento. La comunicación entre subsistemas es una simple llamada a función dentro del mismo espacio de memoria. No hay cambios de contexto, no hay copia de datos entre espacios de memoria, no hay overhead.

Desventaja principal: fragilidad. Un bug en cualquier driver o subsistema (incluso en un driver de terceros añadido después) puede causar un panic y tumbar todo el sistema.

Linux: es monolítico en arquitectura, pero implementa módulos cargables (LKM: Loadable Kernel Modules) que permiten cargar y descargar código en el kernel sin reiniciar. Los drivers de la mayoría de dispositivos se distribuyen como módulos. Esto no cambia la arquitectura fundamentalmente (los módulos cargados ejecutan en modo kernel con acceso total), pero permite distribuir drivers de forma separada del kernel principal.

Microkernel

El kernel se reduce al mínimo absolutamente necesario:
- Gestión del espacio de direcciones (para proporcionar aislamiento entre procesos).
- Comunicación entre procesos (IPC primitiva y eficiente).
- Planificación básica de la CPU.

Todo lo demás (drivers, sistema de archivos, pila de red, gestión de memoria extendida) ejecuta como procesos servidores en modo usuario:

┌────────────────┐ ┌──────────────┐ ┌─────────────┐  Modo usuario
│ Servidor de FS │ │ Servidor Red │ │  Drivers     │
└────────────────┘ └──────────────┘ └─────────────┘
         │                │                │
         └────────────────┴────────────────┘
                          │  IPC (paso de mensajes)
┌─────────────────────────────────────────────────┐  Modo kernel
│        MICROKERNEL: IPC + Memoria + Scheduler   │
└─────────────────────────────────────────────────┘
                       Hardware

Ventaja principal: estabilidad y seguridad. Si el driver de la tarjeta de red falla, solo muere ese proceso servidor; el kernel y el resto del sistema siguen funcionando. El driver puede reiniciarse automáticamente.

Desventaja principal: rendimiento. Cada operación que cruza subsistemas requiere IPC: cambio de contexto (usuario → kernel → usuario), copia de datos entre espacios de memoria diferentes. Una operación de lectura de fichero puede requerir 5-10 mensajes IPC entre el proceso de la aplicación, el servidor de sistema de archivos, el driver de disco y el gestor de memoria. Esto puede ser 10x más lento que en un kernel monolítico.

Ejemplos:
- QNX: RTOS de microkernel usado en automóviles (sistemas infotainment, control de motor), equipos médicos, aviación. La estabilidad es crítica: un fallo en el driver de audio no puede afectar al control del motor.
- Minix 3: famoso como SO educativo. También se usa como firmware interno en los procesadores Intel (Intel ME).
- L4: familia de microkernels de alto rendimiento. seL4 (derivado formal de L4) es el único kernel del mundo con prueba matemática formal de correctitud.

Kernel Híbrido

Adopta la arquitectura de microkernel en diseño pero mueve algunos servicios de vuelta al modo kernel por razones de rendimiento.

Windows NT (y toda la familia Windows hasta Windows 11): originalmente diseñado con influencia de microkernel. El diseño incluye un ejecutivo del kernel (memoria, E/S, seguridad, objetos) y subsistemas de entorno en modo usuario. Sin embargo, en la práctica Microsoft movió progresivamente más código a modo kernel (el subsistema gráfico Win32k se movió al kernel en Windows NT 4.0 por rendimiento). Resultado: un kernel híbrido en la práctica.

macOS (XNU): combina el microkernel Mach (desarrollado en Carnegie Mellon) con el SO BSD (Berkeley Software Distribution). Mach proporciona la abstracción de tareas, hilos, memoria virtual e IPC. BSD proporciona la syscall POSIX, el sistema de ficheros, la red. El resultado es un kernel que mezcla microkernel y código monolítico.

Exokernel

Arquitectura experimental donde el kernel no abstrae el hardware sino que lo expone directamente a las aplicaciones, con mínimas comprobaciones de seguridad. Las aplicaciones implementan sus propias abstracciones (su propia gestión de memoria, su propio sistema de ficheros). Máximo rendimiento pero enorme complejidad para el desarrollador.

Estado actual: principalmente en investigación académica (MIT). No hay SO de producción basados en exokernel. Sin embargo, sus ideas han influido en el diseño de hipervisores y sistemas de E/S de alta velocidad (DPDK para redes, io_uring en Linux).


4. INTERFAZ DE USUARIO DEL SO

4.1 CLI vs GUI: análisis comparativo

La interfaz de usuario no es solo estética: tiene implicaciones profundas en administración, automatización y eficiencia.

Aspecto CLI GUI
Consumo de recursos Mínimo (~MB) Alto (~GB para el servidor gráfico + escritorio)
Automatización Excelente (scripts bash, PowerShell) Difícil (requiere herramientas de automatización de UI)
Acceso remoto SSH: conexión segura con ancho de banda mínimo (~KB/s) RDP/VNC: requiere ancho de banda considerable (~MB/s)
Precisión Exacta (comandos son inequívocos) Puede haber ambigüedad (clic en lugar incorrecto)
Reproducibilidad Total (el mismo script da el mismo resultado) No garantizada (interfaz puede cambiar entre versiones)
Curva de aprendizaje Pronunciada Suave para usuarios básicos
Documentación/Scripting Natural (copiar/pegar comandos) Requiere herramientas especiales (Selenium, AutoHotkey)

Por qué los servidores en producción no tienen GUI: un servidor Linux en producción típicamente no tiene entorno gráfico instalado. Ahorra RAM (el servidor X + escritorio pueden consumir 500 MB-2 GB), reduce la superficie de ataque (menos software = menos vulnerabilidades), y la administración se hace por SSH.

4.2 Shells de Linux/Unix

bash (Bourne Again Shell)

Shell por defecto en Ubuntu, Debian, Red Hat y la mayoría de distribuciones Linux. Es el shell estándar de facto para scripting en Unix/Linux.

Características importantes para administración:

# Variables
NOMBRE="mundo"
echo "Hola, $NOMBRE"

# Condicionales
if [ -f "/etc/passwd" ]; then
    echo "El fichero existe"
fi

# Bucles
for usuario in alice bob carol; do
    useradd $usuario
done

# Tuberías y redirección
ls -la /etc | grep "^d" | wc -l    # cuenta directorios en /etc
cat /var/log/auth.log | grep "Failed" > fallos.txt  # redirige a fichero
chmod 755 script.sh && ./script.sh  # ejecuta si chmod tuvo éxito

# Expansión de llaves
mkdir -p proyecto/{src,bin,docs,tests}  # crea 4 directorios de golpe

# Proceso en segundo plano
./proceso_largo &    # el & lo envía al background

PowerShell

Shell moderno de Microsoft, orientado a objetos. A diferencia de bash (donde todo es texto), en PowerShell los comandos (llamados cmdlets) devuelven objetos .NET, lo que hace el procesamiento de datos mucho más robusto.

# Obtener procesos que usan más de 100 MB de RAM
Get-Process | Where-Object { $_.WorkingSet64 -gt 100MB } | Sort-Object WorkingSet64 -Descending

# Gestión de servicios
Get-Service | Where-Object { $_.Status -eq "Running" }
Stop-Service -Name "Spooler"

# Gestión de ficheros
Get-ChildItem C:\Windows -Filter "*.log" -Recurse | Remove-Item

# Active Directory
Get-ADUser -Filter { Department -eq "IT" } | Select-Object Name, Email

4.3 Comandos Linux del examen: análisis técnico completo

pwd — Print Working Directory

$ pwd
/home/usuario/documentos

Qué hace: muestra la ruta absoluta del directorio de trabajo actual del proceso (shell).

Syscall: getcwd(buffer, size) — el kernel recorre la cadena de directorios desde el directorio actual hasta la raíz (/) consultando los inodos.

Caso de uso típico: en scripts, para saber desde dónde se está ejecutando y construir rutas absolutas: SCRIPT_DIR=$(pwd).

Peculiaridad: si el directorio actual ha sido borrado (se puede borrar un directorio si no hay ningún proceso con él abierto excepto el proceso actual), pwd puede dar resultados inesperados.


sudo — Substitute User Do

$ sudo apt update                    # ejecuta como root
$ sudo -u postgres psql              # ejecuta como usuario 'postgres'
$ sudo -l                            # lista qué comandos puede ejecutar con sudo
$ sudo -i                            # abre una shell interactiva como root

¿Cómo funciona exactamente?

  1. El ejecutable /usr/bin/sudo tiene el bit SUID activado y es propiedad de root.
  2. Cuando un usuario lo ejecuta, el proceso sudo se inicia con EUID (Effective User ID) = 0 (root), aunque el usuario sea UID=1000.
  3. sudo comprueba la identidad del usuario (normalmente pide su propia contraseña, no la de root).
  4. sudo consulta /etc/sudoers (o /etc/sudoers.d/) para verificar si ese usuario tiene permiso para ejecutar ese comando como ese usuario (root u otro).
  5. Si tiene permiso, sudo llama a setuid(0) para establecer el UID real también a 0, y luego a execve() para ejecutar el comando solicitado.
  6. Cada uso de sudo queda registrado en /var/log/auth.log:
Jun  9 10:30:15 servidor sudo: usuario : TTY=pts/0 ; PWD=/home/usuario ; 
USER=root ; COMMAND=/usr/bin/apt update

Formato del fichero /etc/sudoers:

# Quien   Dónde=(como quién)   Qué comando
root       ALL=(ALL:ALL)        ALL
usuario    ALL=(ALL:ALL)        ALL
%admins    ALL=(ALL)            /usr/bin/apt, /usr/bin/systemctl

Diferencia entre su y sudo:
- su pide la contraseña de ROOT para convertirse en root completamente.
- sudo pide la contraseña del propio usuario y ejecuta solo el comando especificado. Principio de mínimo privilegio: cada comando privilegiado requiere autorización explícita. Más auditable.


touch — Actualizar timestamps / crear fichero

$ touch fichero.txt              # crea vacío si no existe; actualiza timestamps si existe
$ touch -t 202506091200 f.txt    # establece timestamp específico (formato YYYYMMDDhhmm)
$ touch -r referencia.txt f.txt  # copia los timestamps de referencia.txt a f.txt

¿Qué timestamps actualiza? Actualiza atime (último acceso) y mtime (última modificación) al tiempo actual. No modifica ctime de la forma habitual (ctime es el momento del último cambio de metadatos).

Syscalls usadas:
- Si el fichero no existe: open(path, O_CREAT|O_WRONLY, 0666) seguido de close().
- Si el fichero existe: utimensat(AT_FDCWD, path, times, 0).

Usos típicos en administración:

# Crear múltiples ficheros de una vez
touch {fichero1,fichero2,fichero3}.txt

# Crear un fichero de marca de tiempo (lock file)
touch /tmp/proceso.lock

# En Makefiles: "tocar" un fichero para forzar que Make lo recompile
touch fuente.c


chmod — Change Mode

$ chmod 755 script.sh              # notación octal
$ chmod u+x script.sh              # notación simbólica: añade x al propietario
$ chmod g=rx,o= fichero            # grupo: solo rx; otros: sin permisos
$ chmod -R 644 /var/www/html       # recursivo: todos los ficheros del directorio
$ chmod a-x fichero_datos.csv      # quita ejecución a todos (buena práctica para datos)

Syscall: chmod(const char *pathname, mode_t mode) o fchmod(int fd, mode_t mode).

Impacto en seguridad: chmod es el comando que más directamente controla la seguridad del sistema de archivos. Errores comunes y peligrosos:
- chmod 777 /etc/passwd → cualquiera puede modificar las cuentas del sistema.
- chmod 777 ~/.ssh/authorized_keys → SSH rechazará la clave por permisos inseguros.
- chmod -R 777 /var/www → cualquier proceso del servidor web puede modificar todos los ficheros.

Umask: el valor por defecto de los permisos al crear nuevos ficheros está determinado por la umask del proceso. La umask es una máscara de bits que se resta de los permisos por defecto (666 para ficheros, 777 para directorios). Umask típica: 022 → ficheros se crean con 644, directorios con 755.


kill — Enviar señales a procesos

$ kill 1234                  # SIGTERM (15) al proceso 1234: terminación elegante
$ kill -9 1234               # SIGKILL (9): terminación forzosa e inmediata
$ kill -SIGTERM 1234         # equivalente al primero (nombre de señal)
$ kill -l                    # lista todas las señales disponibles
$ kill -0 1234               # comprueba si el proceso existe (sin enviar señal real)
$ killall firefox            # envía SIGTERM a todos los procesos llamados "firefox"
$ pkill -9 -u usuario        # envía SIGKILL a todos los procesos del usuario

Flujo detallado de kill -15 1234:
1. El shell ejecuta el programa /usr/bin/kill.
2. kill llama a la syscall kill(1234, SIGTERM).
3. El kernel verifica que el proceso que llama (el shell) tiene permiso para enviar señales al proceso 1234 (debe ser el mismo usuario o root).
4. El kernel añade la señal SIGTERM a la cola de señales pendientes del proceso 1234.
5. La próxima vez que el planificador ejecuta el proceso 1234, antes de reanudar su código normal, el kernel verifica si hay señales pendientes.
6. El kernel "entrega" la señal: si el proceso tiene un manejador de señal registrado para SIGTERM, lo ejecuta; si no, el comportamiento por defecto de SIGTERM es terminar el proceso.
7. El proceso termina y el kernel libera sus recursos (memoria, ficheros abiertos, etc.).

¿Por qué SIGKILL (9) no puede bloquearse?
SIGTERM puede ser capturado por el proceso para hacer cleanup (cerrar ficheros, guardar estado, liberar recursos). SIGKILL es manejado directamente por el kernel y destruye el proceso inmediatamente sin darle ninguna oportunidad de ejecutar código. Esto garantiza que siempre funciona para terminar un proceso, pero puede dejar ficheros corruptos si el proceso estaba en mitad de una escritura.


5. ARRANQUE DEL SISTEMA (BOOT)

El proceso de arranque es la secuencia de eventos que ocurren desde que se enciende el hardware hasta que el SO está listo para el usuario. Es un proceso en cascada donde cada etapa carga y verifica la siguiente.

5.1 BIOS vs UEFI: análisis detallado

BIOS (Basic Input/Output System)

Firmware almacenado en un chip ROM de la placa base desde los años 80. Su diseño original data del IBM PC de 1981 y arrastra muchas limitaciones por compatibilidad:

UEFI (Unified Extensible Firmware Interface)

Estándar moderno desarrollado originalmente por Intel (EFI) y ahora gestionado por el consorcio UEFI. Disponible en prácticamente todo hardware desde 2010-2012.

Mejoras sobre BIOS:

5.2 Proceso de arranque completo con detalle técnico

FASE 0 — POWER ON
────────────────────────────────────────────────────────────────
• El procesador inicia en un estado definido (modo real, CS:IP apunta al firmware)
• La CPU ejecuta la primera instrucción desde la dirección del chip ROM del firmware

FASE 1 — POST (Power-On Self Test)
────────────────────────────────────────────────────────────────
• El firmware prueba la CPU, la RAM (patrón de escritura/lectura), los buses
• Inicializa el hardware básico: controlador de memoria, chipset, buses PCI/PCIe
• Detecta y enumera dispositivos: discos, USBs, tarjetas de red
• Si algo falla → pitidos de error o mensajes en pantalla

FASE 2 — DETECCIÓN DEL DISPOSITIVO DE ARRANQUE
────────────────────────────────────────────────────────────────
BIOS: Busca en la lista de dispositivos de arranque (configurable). Para cada uno:
      • Lee el primer sector (MBR, 512 bytes)
      • Verifica que los últimos 2 bytes son 0x55, 0xAA (firma MBR válida)
      • Transfiere el control al código del MBR

UEFI: Lee la tabla de variables NVRAM que lista las entradas de arranque
      (cada SO instalado registra su entrada durante la instalación)
      • Monta la ESP (partición FAT32)
      • Carga y ejecuta el fichero .efi correspondiente (p.ej. \EFI\ubuntu\grubx64.efi)
      • Si Secure Boot está activo, verifica la firma antes de ejecutar

FASE 3 — BOOTLOADER
────────────────────────────────────────────────────────────────
GRUB2 (Linux):
  • El código inicial de GRUB (Stage 1, en el MBR o en la ESP) carga el módulo
    principal de GRUB (Stage 2) desde el disco
  • GRUB puede leer sistemas de archivos (ext4, NTFS, btrfs, XFS...)
  • Muestra el menú de arranque (si está configurado para ello)
  • Carga el kernel (vmlinuz) e initrd (initial RAM disk) en memoria
  • Pasa los parámetros de kernel (cmdline) y transfiere el control al kernel

Windows Boot Manager:
  • Cargado desde \EFI\Microsoft\Boot\bootmgfw.efi (UEFI) o MBR (BIOS)
  • Lee el BCD (Boot Configuration Database) en la ESP o en la partición de sistema
  • Muestra el menú de arranque si hay varias entradas
  • Carga y verifica el kernel de Windows (ntoskrnl.exe)

FASE 4 — KERNEL (inicialización)
────────────────────────────────────────────────────────────────
Linux:
  1. El kernel se descomprime a sí mismo en RAM
  2. Detecta el hardware usando la información del firmware (ACPI, DeviceTree)
  3. Inicializa la gestión de memoria (paginación, zonas de memoria)
  4. Crea el proceso PID 0 (el proceso idle/swapper, solo ejecuta cuando no hay nada más)
  5. Monta el initrd (un sistema de archivos RAM temporal) como sistema raíz provisional
  6. Carga los módulos de drivers necesarios para acceder al disco real
  7. Monta el sistema de archivos raíz real (/)
  8. Ejecuta /sbin/init o systemd como PID 1 (el primer proceso de usuario)

Windows:
  1. El kernel (ntoskrnl.exe) se carga
  2. Inicializa el HAL (Hardware Abstraction Layer)
  3. Carga drivers críticos del inicio
  4. Inicializa subsistemas del ejecutivo (memoria, procesos, E/S, seguridad)
  5. Lanza smss.exe (Session Manager) como el primer proceso de usuario

FASE 5 — INIT / SYSTEMD (Linux) / Session Manager (Windows)
────────────────────────────────────────────────────────────────
Linux (systemd):
  • PID 1: systemd es el padre de todos los procesos de usuario
  • Lee las unidades (units) de /etc/systemd/system/ y /lib/systemd/system/
  • Arranca servicios en paralelo según sus dependencias declaradas
  • Monta sistemas de archivos adicionales (/proc, /sys, /dev...)
  • Activa la red, el servidor de logs (journald), el gestor de dispositivos (udev)
  • Alcanza el "target" de arranque (graphical.target o multi-user.target)
  • Lanza el gestor de login (getty, GDM, LightDM...)

Windows:
  • smss.exe inicializa la sesión del sistema, carga win32k.sys (subsistema gráfico)
  • services.exe arranca todos los servicios de Windows (en paralelo donde es posible)
  • winlogon.exe gestiona el proceso de inicio de sesión

FASE 6 — LOGIN
────────────────────────────────────────────────────────────────
• Se presenta la pantalla de login (gráfica o en terminal)
• El usuario introduce sus credenciales
• El subsistema de autenticación (PAM en Linux, LSASS en Windows) las verifica
• Se crea la sesión del usuario y se lanza su entorno (escritorio o shell)

6. EVOLUCIÓN HISTÓRICA DE LOS SO

La historia de los SO no es solo arqueología: explica por qué las cosas son como son hoy. Cada generación resolvió los problemas de la anterior e introdujo nuevos conceptos.

Primera generación (1945–1955): sin sistema operativo

Los primeros ordenadores (ENIAC, 1945; UNIVAC I, 1951) son máquinas de válvulas que ocupan salas enteras. No hay sistema operativo. El programador es también operador: programa directamente configurando interruptores, conectando cables (plugboards) o leyendo tarjetas perforadas. Un solo trabajo a la vez. La CPU está ociosa mientras el operador prepara el siguiente trabajo.

Legado conceptual: la idea de que el ordenador hace "un trabajo a la vez" y necesita un operador humano se superará en la siguiente generación.

Segunda generación (1955–1965): procesamiento por lotes (batch)

Los transistores reemplazan las válvulas: ordenadores más pequeños, fiables y asequibles (aunque siguen ocupando habitaciones). Aparecen los primeros ordenadores comerciales: IBM 701 (1952), IBM 7090 (1959).

El sistema de lotes: los programas (en tarjetas perforadas) se agrupan en lotes y se procesan secuencialmente. Aparece el monitor residente: un pequeño programa que permanece en memoria y carga automáticamente el siguiente trabajo cuando el anterior termina. Es el precursor del SO.

Problema pendiente: la CPU sigue ociosa mientras el lector de tarjetas o la impresora trabajan. Si un trabajo tarda 10 ms en CPU pero 990 ms en imprimir resultados, la CPU está ociosa el 99% del tiempo.

Tercera generación (1965–1980): multiprogramación y tiempo compartido

El hito: IBM System/360 (1964). Primera familia de ordenadores con arquitectura unificada: el mismo SO (OS/360) corre en modelos de diferentes tamaños. El concepto de familia de computadoras compatible es revolucionario.

Multiprogramación: varios trabajos residen en memoria simultáneamente. Cuando uno espera E/S, la CPU ejecuta otro. La utilización de CPU puede subir del 20% al 80%.

Tiempo compartido (time-sharing): varios usuarios conectados por terminales de teletipo usan el mismo ordenador de forma aparentemente simultánea. El SO reparte la CPU entre los usuarios en pequeñas ranuras de tiempo.

MULTICS (1969): proyecto conjunto MIT/Bell Labs/GE para crear el "SO definitivo". Demasiado ambicioso, nunca tuvo éxito comercial. Pero de su fracaso nació algo mejor:

UNIX (1969): Ken Thompson y Dennis Ritchie, insatisfechos con MULTICS pero habiendo aprendido de él, crearon UNIX en los Bell Labs con una filosofía radicalmente diferente: simple, elegante, portable. UNIX introduce conceptos que siguen siendo fundamentales hoy: todo es un fichero, procesos como abstracción central, shell como lenguaje de scripting, tuberías (pipes), el árbol de directorios con raíz /. Escrito en C (lenguaje también inventado por Ritchie), UNIX puede portarse a diferentes arquitecturas hardware recompilando el código fuente.

Cuarta generación (1980–2000): PC, GUI y Linux

Los microprocesadores (Intel 4004, 1971; Intel 8086, 1978) hacen los ordenadores asequibles para individuos y pequeñas empresas.

1981 — IBM PC y MS-DOS: IBM lanza el PC con el SO MS-DOS de Microsoft. Monousuario, monotarea, línea de comandos. Enormemente exitoso por la apertura de la arquitectura IBM PC compatible. MS-DOS domina la PC durante los 80.

1984 — Macintosh: Apple lanza el Mac con una interfaz gráfica (GUI) basada en ventanas, iconos, menús y puntero. Inspirada en investigaciones de Xerox PARC. Democratiza los ordenadores para usuarios no técnicos.

1985-1995 — Windows: Microsoft lanza Windows como extensión gráfica de MS-DOS. Windows 3.x (1990) se vuelve enormemente popular. Windows 95 (1995) integra MS-DOS y Windows en un solo SO de 32 bits.

1991 — Linux: Linus Torvalds, estudiante finlandés de 21 años, publica en agosto de 1991 en el grupo de noticias comp.os.minix: "Estoy haciendo un SO libre (solo un hobby, no será grande ni profesional como GNU)". Combinado con las herramientas GNU de Richard Stallman (gcc, glibc, bash...), nace el ecosistema GNU/Linux. Hoy, Linux es el SO dominante en servidores, supercomputación, dispositivos móviles (Android) y nube.

1993 — Windows NT: Microsoft lanza Windows NT, diseñado desde cero (no basado en DOS) con arquitectura moderna: 32 bits, kernel híbrido, multiusuario, multiprocesador. Es la base de todos los Windows posteriores (2000, XP, Vista, 7, 8, 10, 11).

Quinta generación (2000–presente): internet, móviles, nube y contenedores

Distribuciones Linux para servidores: Red Hat Enterprise Linux (RHEL), Debian, Ubuntu Server se convierten en el estándar de facto para servidores empresariales. Linux domina la web: Apache y Nginx (servidores web), MySQL/PostgreSQL (bases de datos), todos sobre Linux.

Virtualización: VMware (1998) populariza las máquinas virtuales x86. Un servidor físico puede alojar docenas de VMs. Transforma los centros de datos. Los hipervisores Xen (2003), KVM (2007, integrado en el kernel Linux) y Hyper-V (Microsoft) se convierten en infraestructura crítica.

Móviles: iOS (Apple, 2007, basado en Darwin/BSD) y Android (Google, 2008, basado en el kernel Linux) crean los ecosistemas móviles. Nuevos retos para los SO: gestión agresiva de batería, permisos por aplicación, sandboxing estricto, ciclos de actualización rápidos.

Contenedores: Docker (2013) populariza los contenedores Linux (tecnología que existe desde los años 2000 con LXC y namespaces del kernel). Los contenedores comparten el kernel del anfitrión pero tienen su propio sistema de archivos, red y espacio de procesos. Mucho más ligeros que las VMs. Kubernetes (Google, 2014) orquesta contenedores a escala. El SO moderno de servidor es cada vez más una plataforma para ejecutar contenedores.

Cloud: AWS (2006), Azure (2010), GCP (2011) consolidan el modelo de "infraestructura como código". Las VMs y contenedores se crean, configuran y destruyen automáticamente mediante APIs. El SO se convierte en infraestructura efímera y desechable.


PREGUNTAS DE EXAMEN — ESTILO POLITÉCNICA


Pregunta 1
Como administrador de un servidor Linux, necesitas saber exactamente qué ocurre internamente cuando ejecutas el comando sudo apt update. Describe paso a paso: (a) cómo funciona el mecanismo SUID del ejecutable sudo, (b) cómo verifica sudo que el usuario tiene permiso, (c) qué syscalls están implicadas en el proceso, y (d) dónde queda registrado este evento y qué información contiene ese registro.


Pregunta 2
Un servidor de base de datos muestra un rendimiento degradado. Al analizarlo, observas que el uso de CPU es del 100% pero el sistema responde muy lentamente. Describe cómo determinarías si el sistema está sufriendo thrashing. ¿Qué herramientas de Linux usarías para diagnosticarlo? ¿Qué relación existe entre el sistema de E/S, los fallos de página y la memoria virtual en este escenario? ¿Qué medidas adoptarías para resolverlo?


Pregunta 3
Explica las diferencias fundamentales entre los sistemas de archivos FAT32, NTFS y ext4, indicando para cada uno: estructura interna principal, soporte de journaling, modelo de permisos y casos de uso recomendados. ¿Por qué FAT32 sigue usándose en 2025 a pesar de sus limitaciones? ¿Qué consecuencias tiene la ausencia de journaling ante un apagado brusco del sistema?


Pregunta 4
Describe el proceso completo de arranque de un sistema Windows 11 con UEFI y Secure Boot activado, desde que se pulsa el botón de encendido hasta que aparece la pantalla de login. ¿Qué ventajas de seguridad aporta Secure Boot sobre el arranque BIOS tradicional? ¿Qué tipos de malware intenta prevenir específicamente?


Pregunta 5
Un fichero en Linux tiene los permisos rwxr-x--- y pertenece al usuario ana y al grupo desarrollo. Responde: (a) ¿puede el usuario bob (que pertenece al grupo desarrollo) ejecutar el fichero? (b) ¿puede el usuario carlos (que no pertenece al grupo) leer el fichero? (c) ¿qué comando usaría ana para dar permiso de lectura a todos los usuarios sin cambiar los demás permisos? (d) Expresa los permisos originales en notación octal. (e) ¿Qué bit especial debería activarse si este fichero es un ejecutable que necesita correr siempre con los privilegios del propietario?


Pregunta 6
Compara en detalle las tres técnicas de E/S (polling, interrupciones y DMA) en términos de: eficiencia de CPU, latencia, casos de uso apropiados e implementación. ¿Por qué la mayoría de los sistemas modernos combinan interrupciones con DMA en lugar de usar una sola técnica? Pon un ejemplo concreto de una transferencia de disco de 1 GB describiendo exactamente qué haría la CPU con cada técnica.


Pregunta 7
Explica el concepto de journaling en los sistemas de archivos. ¿Qué problema resuelve? Describe los tres modos de journaling de ext4 (writeback, ordered, journal) indicando las diferencias en rendimiento y seguridad de datos. ¿Por qué un sistema de archivos sin journaling (como FAT32) es problemático en entornos de producción? ¿Cómo se relaciona el journaling con la recuperación ante desastres?


Pregunta 8
Un administrador quiere implementar un control de acceso granular en un servidor Windows compartido por varios departamentos. Explica la diferencia entre el modelo DAC de Unix (rwx) y las ACLs de NTFS. ¿Qué ventajas tiene NTFS ACL sobre el modelo Unix de tres entidades (propietario/grupo/otros)? Describe cómo configurarías los permisos para un directorio que: el usuario jefe_proyecto tiene control total; el grupo equipo puede leer y ejecutar pero no escribir; los demás usuarios no tienen acceso.


Pregunta 9
Describe las diferencias entre kernel monolítico, microkernel y kernel híbrido en términos de: arquitectura, dónde ejecuta cada subsistema (modo kernel o usuario), rendimiento, estabilidad y ejemplos de SO que los implementan. ¿Por qué Linux, siendo monolítico, es tan estable en producción si teóricamente un driver defectuoso puede tumbar el sistema? ¿Qué mecanismos mitigan este riesgo?


Pregunta 10
Define los conceptos de buffering, caché de E/S (page cache) y spooling en el contexto de la gestión de E/S de un SO. Para cada uno: explica el problema que resuelve, cómo funciona y da un ejemplo práctico. ¿Cómo puede el administrador de un servidor Linux conocer cuánta RAM está siendo usada como page cache en un momento dado? ¿Es deseable que la page cache ocupe mucha RAM? Razona la respuesta.


Fin de la Parte 2 — E/S, Sistema de Archivos, Seguridad, Kernel, Interfaces, Arranque y Evolución