Regístrate | Conectar
El Tamiz Libros Recursos Series Únete 21 Users Online
Skip to content

Computador mágico XXX – Sistema operativo II: funcionamiento




La serie “El computador mágico” está disponible también en forma de libro.

En el último capítulo de esta serie vimos la evolución histórica de los sistemas operativos, y vimos cómo nacían los cuatro componentes más importantes de los sistemas operativos. Lógicamente, no todos los sistemas operativos son iguales. No es lo mismo el sistema operativo de un mainframe que el de tu Nintendo DS, el del cajero automático del banco que el de tu teléfono móvil, el de los servidores de Amazon que el que lleva tu televisor… pero casi todos ellos comparten un conjunto de tareas:

  • Gestión de dispositivos
  • Gestión de procesos
  • Gestión de memoria

Todo lo que vamos a ver en este artículo ya lo hemos visto, aquí simplemente vamos a pegarlo todo para formar un sistema operativo. No todos los sistemas operativos contienen todos estos componentes, o incluso aunque los tengan pueden ser más o menos sofisticados, así que tendremos que contar cosas más o menos generales.

Separación de privilegios

Ya vimos anteriormente que los procesadores modernos tienen dos modos de funcionamiento distintos: uno normal y otro privilegiado. El sistema operativo se ejecuta sobre todo en modo privilegiado, mientras que las aplicaciones se ejecutan siempre en modo normal: cuando necesitan hacer algo privilegiado no lo hacen directamente, sino que se lo piden al sistema operativo, que lo hará, o no lo hará, o lo hará, pero más tarde, o lo que corresponda, dependiendo de muchas cosas que ya veremos (y de muchas otras que no veremos).

Aunque este concepto ya lo hemos visto antes, vamos a volver a contar lo más importante aquí para que lo puedas contextualizar con el resto del artículo.

Las instrucciones privilegiadas más importantes son:

  • Configuración de las interrupciones
  • Configuración de la pila
  • Configuración de los elementos hardware que controlan el resto de componentes
  • Operaciones de entrada y salida hacia y desde los periféricos

Las instrucciones normales más importantes son:

  • Operaciones aritméticas y lógicas
  • Traer y llevar datos a y desde la memoria principal… pero solo de la memoria que sea mía (ya veremos eso)
  • Poner y quitar datos en la pila… pero no configurarla (eso lo vimos antes)
  • Saltos y subrutinas… pero no a zonas de la memoria que no son mías (otra vez)
  • Interrupción software o petición al sistema; por si no la recuerdas, esta instrucción era como una interrupción más, que saltaba a una posición conocida (en la cual quien estaba era el sistema operativo)

Funcionamiento basado en interrupciones

Este concepto también lo hemos visto antes, pero vamos a enfatizarlo aquí: en un sistema operativo moderno, todo ocurre porque ha llegado una interrupción (salvo la inicialización, claro).

Cuando el ordenador arranca (más adelante veremos todo el proceso de arranque), a quien está ejecutando es al sistema operativo, que durante su inicialización configura la pila, configura todos los dispositivos que tiene y, lo más importante desde este punto de vista, configura el vector de interrupciones. El vector de interrupciones contiene la dirección de memoria que debe ejecutarse cuando ocurra cada interrupción. La gracia es que quien está en esas posiciones de memoria es siempre el sistema operativo, de modo que será siempre siempre el sistema operativo quien atienda cualquier interrupción.

Podemos dividir las interrupciones en los siguientes grupos:

  • La interrupciones generadas por los dispositivos: siempre que un dispositivo (por ejemplo un teclado, un disco duro, una tarjeta de sonido…) quiere decirle algo a la CPU, levanta una interrupción, y ahí está el sistema operativo para procesarla.
  • Una particular de las anteriores: un reloj. Los ordenadores tienen un reloj que genera interrupciones cada cierto tiempo (como ejemplo, digamos que cada 1ms)… cada vez que el reloj genera una interrupción, ahí está el sistema operativo para hacer algo.[1]
  • La interrupción software: siempre que una aplicación de usuario necesita pedirle alguna cosa al sistema operativo, lanza una interrupción software, y ahí está el sistema operativo para procesar la petición.
  • Las interrupciones debidas a error: cuando ocurre un error, los propios componentes del ordenador generan una interrupción… y ahí está el sistema operativo para hacer algo al respecto, si puede.

Gestión de procesos

Las gestión de procesos, como su propio nombre indica, se encarga de gestionar procesos. ¿Y qué es un proceso? Pues… un proceso es la unidad mínima que gestiona el componente de gestión de procesos. Está bien, eso es una definición tautológica, así que que, para la profundidad que vamos a darle a este texto, vamos a decir que un proceso es un programa: el navegador, el lector de correo, tu procesador de textos… pero también muchos otros procesos que el ordenador necesita para funcionar y que probablemente ni siquiera sabes que existen.

Parte del árbol de procesos en un Windows 7, obtenido con Process Explorer

Por lo tanto, tal y como hemos visto, la función más importante de la gestión de procesos es ir asignando la CPU a los procesos cada vez que les toca. El sistema de gestión de procesos tiene una lista con todos los procesos del sistema y su estado. Cuando un proceso esté realizando una operación de entrada/salida (que ya hemos visto que tardan mucho), el sistema de gestión de procesos lo saca de la CPU, busca uno que esté listo para ejecutar y lo pone en la CPU. También realiza esa operación periódicamente, usando el reloj que describíamos más arriba: cada 1ms (por ejemplo) saca de la CPU al proceso que esté y pone al siguiente en la lista (habitualmente esto se puede combinar con algún tipo de gestión de prioridad, por ejemplo como se puede ver en Windows 7 en la siguiente figura).

Asignación de prioridad de un proceso, en Process Explorer

¿Y qué significa eso de “sacar al proceso de la CPU” o “poner al proceso en la CPU”? Eso es lo que se llama un cambio de contexto. Cuando sacamos un proceso de la CPU, queremos que, cuando luego lo volvamos a meter, continúe por donde iba, exactamente con el mismo estado, como si nada hubiera pasado entre medias. Lo que haya que guardar exactamente depende del procesador y del sistema operativo, pero lo habitual es que haya que guardar el contador de programa PC, el puntero de la pila SP y todos los registros que tenga la CPU (a menudo hay que guardar alguna cosa más, pero son cosas que no hemos visto). Los tomamos con mucho cuidado y los guardamos en la descripción de nuestro proceso. Luego, cuando queramos volver a poner ese proceso en la CPU, simplemente volvemos a copiar esos datos desde la descripción del proceso a la CPU y seguimos ejecutando por donde dijera el PC: desde el punto de vista del proceso que se estaba ejecutando, no ha cambiado nada, para él todo sigue como estaba.

Así, un proceso es una cosa abstracta, un hilo de ejecución, un programa, que vamos “poniendo en la CPU” de vez en cuando.

Gestión de memoria

Cuando diseñamos nuestro ordenador, la memoria simplemente estaba ahí, lista para ser usada por la CPU. Pero ahora queremos que distintos procesos accedan a distintas partes de la memoria, pero no a otras. Más aún: aunque no lo hemos visto, en general queremos que cada proceso vea toda la memoria como si fuera toooooda para él, como si él fuera el único proceso ejecutándose en la máquina.

Para ello necesitamos introducir un nuevo componente hardware, situándolo entre la CPU y la memoria principal. Vamos a llamar a este componente MMU (Memory Management Unit, unidad de gestión de memoria); todas las CPUs modernas tienen una MMU.

Cuando la MMU se ve desde la CPU, se comporta como si fuera directamente la memoria principal MP. Es decir, la CPU le pide la posición 0xA1B2C3D4 y le da su contenido; le pide guardar algo en la posición 0xE5F6A7B8 y lo guarda. ¿Cómo lo hace? Mandándolas a la MP, obviamente, no puede hacerlo de otro modo.

La gracia está en que el mapeo en la posición que me pide la CPU y la posición correspondiente en la MP es configurable. Así, yo puedo configurar la MMU para decirle: siempre que te pidan las posiciones desde la 0×00000000 a la 0x0000FFFF, utiliza en realidad las que van desde 0xA0000000 a 0xA000FFFF. Y así para todas las posiciones de memoria posibles. El truco está en que el módulo de gestión de memoria decide hacer mapeos distintos para procesos distintos, de modo que cada vez que el sistema de gestión de procesos mete un proceso en la CPU, también cambia la configuración de la MMU para que el proceso en cuestión crea que tiene toda la memoria disponible, pero en realidad solo pueda acceder a las posiciones que tiene asignadas. Eso quiere decir que los procesos ya no pueden simplemente acceder a la memoria, sino que antes de hacerlo deben pedírsela al sistema operativo, y tienen que “liberarla” cuando hayan terminado de usarla.

Estado de la memoria en un Windows 7

Gestión de dispositivos

Hemos visto que una de las funciones más importantes del sistema operativo es abstraer el uso de los dispositivos: nosotros usamos de la misma manera un teclado Logitech y uno de Trust, una pantalla de HP y una de LG, un disco duro Seagate y uno de Western Digital, una tarjeta gráfica de MSI y una de AMD…

Así que el sistema operativo agrupa los dispositivos por categorías y define una forma estándar de usarlo. Y luego cada fabricante de dispositivos proporciona una piececita de software para traducir esa forma estándar a lo que su dispositivo específico necesita. Esa piececita es lo que se llama un driver de dispositivo.

Vista parcial de dispositivos en un PC con Windows 7

Además, el sistema operativo se encarga de que los dispositivos se utilicen de forma ordenada.

Vamos a ver el ejemplo de una tarjeta de sonido, que tiene tanto entrada (el conector del micrófono) como salida (la salida de línea que conectamos a los altavoces). Cuando un proceso en cuestión necesita reproducir sonido no se pone directamente a enviarle datos a la tarjeta de sonido (recuerda que, como hemos visto, probablemente enviar sonido a la tarjeta sea algo tan “sencillo” como escribir una cierta información en unas determinadas posiciones de memoria). Si lo intentara, no podría, porque la MMU o la propia separación de privilegios de la CPU se lo impedirían. En lugar de eso, cuando necesita enviar sonido a la tarjeta, deja los sonidos (debidamente codificados) en la pila y genera una interrupción software.

Sabemos que quien atenderá esa interrupción será siempre el sistema operativo, en concreto su módulo de gestión de dispositivos, que tomará los sonidos que hay en la pila, y se los dará al driver de la tarjeta de sonido, que, ahora sí, los enviará a la tarjeta de sonido, que los reproducirá.

En el sentido contrario es parecido. Cuando un proceso necesita recibir sonido del micrófono (por ejemplo, porque sea un programa de videoconferencia) utiliza la interrupción software para decirle al sistema operativo “eh, a partir de ahora quiero recibir el sonido del micrófono; cuando tengas algo dáselo a esta subrutina mía”. Y el sistema operativo se lo apuntará en una tabla. Cuando ahora llegue sonido a través del micrófono, ¿qué hará la tarjeta? Generará una interrupción, que atenderá el sistema operativo (en realidad, quizá lo haga el driver del fabricante, pero eso es parte del sistema operativo); el sistema recibirá el sonido de la tarjeta y se lo dará a la subrutina en cuestión del proceso en cuestión.

Sistema de ficheros

Existe un componente más que, por su importancia, suele nombrarse aparte: el sistema de ficheros. Todos lo hemos usado alguna vez, así que seguro que lo entiendes rápido.

Vista parcial de un sistema de ficheros en Windows 7

En los discos duros no se lee y escribe directamente, ni siquiera a través del driver correspondiente, sino que el sistema operativo ofrece un nivel de abstracción más: los ficheros. El sistema operativo ofrece el concepto de fichero como una sucesión de bytes, y el de directorio (o carpeta, en terminología Microsoft) para organizar ficheros, y luego ofrece formas de acceder a ellos, de listar su contenido, de abrirlo y cerrarlo…

No podemos entrar en mucha profundidad, porque cada sistema de ficheros es distinto y contar los detalles llevaría un libro completo. Así que vamos a ver por encima cómo funciona uno de los sistemas de ficheros más extendidos: FAT (existen otros, mucho más sofisticados y potentes, pero también mucho más difíciles de entender). Probablemente uses el sistema de ficheros de tipo FAT en un montón de sitios, sobre todo en tarjetas de memoria o pendrives USB.

Para empezar a explicarlo hay que entender que los discos no se leen byte a byte, sino bloque a bloque (de hecho, se les llama genéricamente así, dispositivo de bloque, tanto si son un disco magnético clásico como un pendrive, un CDROM o cualquier cosa que pueda parecer un disco). El tamaño de dichos bloques depende de la tecnología y el fabricante, pero supongamos que se leen en bloques de 1kB (1024 bytes) y que nuestro disco es pequeñito, de solo 16kB.

 

Lo que tenemos son 16 bloques de 1kB cada uno. El primero de ellos es un poco especial, porque lo que contiene es la tabla de asignación de ficheros (en inglés, File Asignation Table… FAT… de ahí el nombre). Y ahora supongamos que tenemos un fichero llamado “leeme.txt” que en su descripción dice que su primer bloque es el 2. Así que sabemos que está en el bloque 2 y quizá en alguno más. Nos vamos a la tabla de asignación del ficheros del primer bloque y vemos que en la posición 2 hay un 11… eso quiere decir que continúa en el 11. Ya tenemos el 2 y el 11. Miramos en la posición 11 y vemos un 8, así que continúa en el 8. Seguimos buscando así y tenemos el 7 y un -1. El -1 indica que se ha terminado, así que ya sabemos que el fichero “leeme.txt” está en los bloques 2, 11, 8 y 7. Así que cuando queramos leer ese fichero, esos son los bloques que debemos pedirle al disco duro.

De esta forma tan tonta funciona el sistema de ficheros FAT, y por eso se usa tanto en aparatos sencillos: porque es muy fácil de implementar.

¿Y en realidad?

Pues en realidad es un poco más complejo. Los sistemas de ficheros son mucho más sofisticados, y de hecho puedes tener más de uno a la vez; los drivers de dispositivos pueden ser millones, y en realidad hay dispositivos que ni siquiera funcionan exactamente así (como pueden ser las impresoras); no todas las tareas del sistema operativo se hacen durante las interrupciones; gestionar memoria y procesos es mucho más complicado de lo que hemos visto aquí; en fin… esto es una introducción. Lo que aquí hemos contado en un solo artículo puede representar un libro completo o un curso completo en cualquier carrera universitaria del ramo… pero lo fundamental lo tienes ahí. Cuando demos referencias al final podrás profundizar más, si lo deseas.

En el próximo capítulo veremos cómo arrancar el ordenador.

 

 

  1. No confundir este reloj con el reloj del procesador, que va a 1GHz o algo de ese orden de magnitud. Este es un reloj específico para generar estas interrupciones. []

Sobre el autor:

J ( )

 

Escribe un comentario

Tu dirección de correo no es mostrada. Los campos requeridos están marcados *

Al escribir un comentario aquí nos otorgas el permiso irrevocable de reproducir tus palabras y tu nombre/sitio web como atribución.