Sinclair QL Programación Avanzada
Anterior Siguiente

3. QDOS - Visión general

3.1 Introducción

La intención de este capítulo es presentarle los conceptos fundamentales del QDOS. Las explicaciones detalladas de aspectos particulares se han dejado para los capítulos de referencia en la última mitad del libro.

El QL se diferencia de otros ordenadores en el hecho de que soporta trabajos en multitarea. Esto significa que pueden trabajar al mismo tiempo varios programas completamente independientes.

Si se piensa un poco, se ve que este método de operación no es tan complejo como parece en un principio. Por ejemplo, usted puede querer jugar al ajedrez contra su QL. Los movimientos se pueden hacer sobre la base de un movimiento diario. Esto permitiría al QL ejecutar gran cantidad de análisis complejos de los movimientos, pero no podría usarlo para ninguna otra cosa durante este tiempo. Aquí es donde se puede apreciar el uso real de los trabajos en multitarea. Si el programa de ajedrez se prepara como un trabajo de baja prioridad, puede operar todo el día como un trabajo subordinado. Otros programas, como una aplicación de negocios, juegos u otras tareas generales, pueden ejecutarse con prioridades mayores. Entonces, el QL, usa el procesador para jugar ajedrez solamente cuando no lo requiere otra tarea preferente (ej. cuando la tarea preferente está esperando a que se pulse una tecla).

Otro ejemplo de multitarea es un reloj. La fecha y la hora se pueden ajustar a tiempo de encendido del QL. Después se puede cargar un trabajo que muestre un reloj en la pantalla. Este trabajo puede ejecutarse en prioridad muy baja, de forma que la hora del reloj se actualiza a intervalos regulares.

Resumiendo, un Job es una unidad de programación que opera aislado de las otras unidades de programación en el QL. El programa de la sección 4.4.2 nos muestra la cantidad de Jobs que pueden coexistir.

Ahora pensará que debe ser terriblemente complejo mantener todos estos trabajos ejecutándose al mismo tiempo. En otros sistemas menos potentes, esto podría ser un problema, y nos conduciría a una verdadera confusión del sistema interceptando interrupciones. Sin embargo, en el QL no es demasiado complejo, el QDOS se encarga de las partes más difíciles. Para asegurarse que todos los Jobs coexisten pacíficamente, el QDOS debe comprobar que no usan las mismas áreas de memoria para propósitos diferentes, y que se controla cuidadosamente la asignación de los recursos de la máquina. Por ejemplo, si dos Jobs quieren mandar datos a la impresora al mismo tiempo, se producirían datos ininteligibles, si se mezclaran estas dos salidas. Para evitarlo, el último Job que haya requerido la. impresora, es forzado a esperar a que termine el que la está usando. El QDOS evita este tipo de trabajo al programador, y se asegura de que el segundo Job se encola para imprimir, dejando al primero que termine con su cometido.

En este momento se puede enunciar la regla número uno. USE EL QDOS EN TODO MOMENTO Y NO ESCRIBA PROGRAMAS QUE NO ESTÉN DEBIDAMENTE CONECTADOS DENTRO DEL SISTEMA. Esto significa que el QDOS debe ser siempre el encargado de asignar memoria, canales de impresión, etc. Si el usuario hace, por ejemplo, un POKE de un programa de 68008 directamente en la memoria, podría ser desastroso si el QDOS no tiene noticias de ello. ¿Por qué? Debido a que el mapa de memoria del QDOS está cambiando continuamente, si el QDOS no sabe lo que hay en un área particular, ¡el programa introducido podría ser asignado como área libre de memoria!. Toda la memoria libre es susceptible de ser usada como memoria intermedia al leer o escribir en los microdrives. Por lo tanto el QDOS debe ser avisado cuando se prepara un trabajo o cuando se usa la memoria directamente.

Mientras el QDOS tenga total control de la memoria v de los otros recursos de la máquina, los trabajos operaran en el entorno de multitarea. Las tres secciones del QDOS que realizan el control de la memoria son, gestión de memoria (se asegura que unos trabajos no modifican los datos de otros en la memoria), asignación de recursos (se asegura de que los recursos como la impresora, son usados por un solo trabajo a la vez) y planificación (decide que trabajos deben usar la unidad central de proceso 68008 en cada momento).

3.2 QDOS y control del Sistema

3.2.1 Gestión de memoria

En la sección de introducción decíamos que es necesaria cierta forma de control de la memoria. Sin un buen control, al tener varios trabajos funcionando al mismo tiempo, escribirian unos encima de la memoria de los otros. Una de las misiones principales del QDOS es la de cuidar de la memoria del QL y asegurarse que dos trabajos no pueden usar accidentalmente la misma memoria. Por supuesto, ¡esto no significa que pueda usted ejecutar un programa con errores y esperar que el QDOS proteja el resto de la máquina! Hacer POKES aleatorios en la memoria del QL conducirá inevitablemente a un fallo del sistema. El QDOS sólo es capaz de prevenir programas operacionales que sigan sus reglas. La memoria disponible está dividida en varias secciones (ver figura 3.1).

SV-RAMT-1


SV-RESPR
 

PROCEDIMIENTOS
RESIDENTES
 
  dirección descendente llenado



SV-TRNSP
 

PROGRAMAS
TRANSITORIOS
 
  dirección descendente llenado



SV-BASIC
 

DATOS Y PROGRAMAS
DE SUPERBASIC
 
  dirección descendente llenado




SV-FREE
 

SUBSISTEMA LLENADO
BLOQUES DEPENDIENTES
Y MEMORIA LIBRE
 
   



SV-HEAP
 

CANALES Y OTROS
ITEMS COMUNES
 
  dirección accendente llenado




SV-BASE
 

GESTOR RECURSOS
TABLAS Y
VARIABLES SISTEMA
 
 



28000 Hex.
   

MEMORIA PANTALLA
 
   

Figura 3.1 - Mapa de memoria del QDOS

Usos de la memoria - de arriba hacia abajo

El área de Procedimientos Residentes

Este bloque de memoria es asignado al encender la máquina, y una vez asignado permanece fijo. Toda la memoria entre la parte alta de la RAM disponible (SV.RAMT) y la parte inferior del área (SV.RESPR) está dedicada a procedimeintos residentes. En esta parte de memoria van los programas que son requeridos durante el uso de la máquina. Tenga en cuenta que SV.RAMT varia de una máquina a otra, dependiendo de la cantidad de memoria de extensión de que disponga.

Los procedimientos residentes añadidos al SuperBASIC deben ser colocados en esta área. Los nombres de los procedimientos (o funciones) pueden ser conectados en la lista de nombres del BASIC, de forma que sean accesibles desde el BASIC. En la sección 10.8 puede encontrar un par de ejemplos de procedimientos y funciones. Hay que tener- en cuenta que todos los procedimientos que se definan por este método DEBEN ser re-entrantes e independientes de su posición y NO DEBEN contener ningún código automodificable ni variables locales (en el glosario se explica el significado de estos términos).

El área de Programas Transitorios

Como su propio nombre indica, esta área contiene programas que no son residentes, y que pueden ser eliminados en cualquier momento. La mayoría de los trabajos son colocados en esta área de memoria. Los programas transitorios se cargan inmediatamente debajo de los procedimientos residentes. Cada programa transitorio debe ser auto contenido (código, área de datos y pila). Cualquier programa que no sea reubicable (ej. que debe ser cargado en un área de memoria especifica) ha de ser cargado por un cargador-conector especial. Esto se debe a que los programas transitorios se cargan normalmente mediante el comando EXEC y después se activan como trabajos. La carga mediante este método significa que no se puede garantizar una posición determinada de memoria para un trabajo particular.

Si se usa el área de programas transitorios para otra cosa que no sea contener programas, como almacenar datos, debe tenerse mucho cuidado de que los datos no sean activados. Su activación provocaría un fallo de la máquina.

El área de SuperBASIC

En esta área se almacenan todos los datos relacionados con una operación correcta de SuperBASIC, incluido el programa BASIC tecleado y todas las variables del sistema de BASIC.

Es importante tener en cuenta que esta área de memoria se está moviendo continuamente. Se mueve hacia abajo en la memoria cada vez que se asigna más área de programas transitorios. Se mueve hacia arriba cuando se desasigna parte de esta área. Parte de este área se mueve cuando se teclean nuevas líneas y cambia de tamaño a medida que se van creando nuevos datos durante la ejecución de un programa BASIC.

El mapa completo de memoria del QL está cambiando constantemente. Este sistema es diferente del de la mayoría de los ordenadores pequeños, en donde las diferentes partes se almacenan en posiciones fijas de memoria. Aunque a primera vista pueda parecer- una forma no muy buena de hacer las cosas, en la práctica es bastante limpio. El 68008 puede usar simplemente uno de sus ocho registros de dirección (A6 para el BASIC) para apuntar a la parte inferior de cada área. Todas las operaciones dentro de esa área se realizan con relación a este registro de dirección, creando la ilusión de que todos los datos están en posiciones fijas.

Espacio libre (usado como bloque dependiente del subsistema de relleno)

Esta área se extiende desde la parte inferior del BASIC hasta la parte superior del área de canales de almacenamiento. Normalmente, cuando no se está accediendo a ficheros, esta área está yacía. Sin embargo, cuando se le pide al ODOS que lea o escriba un fichero, se pone en uso.

El acceso a los microdrives es realmente lente. Los ficheros suelen ser bastante largos v están contenidos en más de un sector del cartucho. Si todos los datos requeridos se pueden cargar en memoria de una vez, en vez de hacer lentos accesos a los sectores individuales, nos supondrá una clara ventaja. Esto es lo que hace el QDOS, aunque pase totalmente desapercibido para el usuario, se hace el máximo uso de la memoria disponible, por lo que la copia de ficheros con la máquina yacía es mucho más eficiente. Una vez que la máquina se llena con otros programas (como un programa largo de BASIC), el espacio libre en esta área se hace mucho menor. En este caso, solo se pueden almacenar pequeñas cantidades de datos en memoria, la copia de microdrives consiste en la transferencia de muchos paquetes pequeños de datos desde una unidad a otra - poco eficiente.

El almacenamiento del sistema

Esta área de memoria se usa para almacenar definiciones de canales, datos, memoria de trabajo para el subsistema de E/S etc. El área puede ser expandida o reducida de tamaño por medio de los TRAPS adecuados del gestor correspondiente. Los trabajos pueden reservar memoria en esta área para su propio uso. El sistema se encarga de borrar todas las áreas reservadas por un trabajo cuando éste ha terminado su ejecución. El área de almacenamiento del sistema se explica con más detalle en la sección 5.2.4.

Variables y tablas del sistema y pila del Supervisor

Esta área fija de memoria reside justo sobre la memoria de pantalla. La pila del supervisor es usada por las rutinas que se ejecutan eh modo supervisor en el 68008. Las variables del sistema están listadas en el Apéndice M.

3.2.2 Asignación de recursos

El proceso de asignación de recursos se ocupa de todos los dispositivos que pueden ser direccionados por un trabajo. La pantalla, los microdrives, el teclado, el generador de sonido y la impresora serie son estos recursos. Si hay más de un trabajo que necesita usar un dispositivo al mismo tiempo, solamente uno de ellos lo podrá hacer. El resultado de una asignación correcta de recursos es el asegurarse de que el primer trabajo tiene prioridad y el segundo es colocado en modo de espera hasta que el primero haya terminado.

El proceso de asignación de recursos se controla mediante los TRAPS del gestor (capítulo 5) v los TRAPS de asignación de E/S (capítulo 6).

3.2.3 Planificación de tareas

Hay varios aspectos de la planificación de tareas en una máquina multitarea. La CPU 68008 solo puede realizar un Job a la vez. Si se permitiera a un Job ejecutarse sin la intervención del planificador, no habría manera de evitar que usara todo el tiempo de CPU para sí mismo. Aquí es donde hace falta la intervención del planificador.

Siempre que se crea un Job, se la asigna una prioridad. Esta prioridad determina la forma de compartir el tiempo de la CPU de un Job concreto. Un Job con baja prioridad (1), solo podrá usar la CPU una décima parte del tiempo dado a otro Job con prioridad 10. La prioridad puede ser entre 0 (en cuyo caso el trabajo no coje nunca tiempo de la CPU) hasta 127. El intérprete de comandos BASIC se ejecuta como Job 0 y suele tener prioridad 32.

Los Jobs pueden estar en uno de los tres estados siguientes:

Activo: Tienen una prioridad entre 1 y 127, y comparten los recursos de la CPU, de acuerdo con la prioridad.

Suspendido: Son los capaces de ejecutarse (prioridad entre 1 y 127), pero que no están funcionando por esperar a otro Job o E/S. El planificador rearrancará automáticamente un Job suspendido tan pronto como termine aquel por el que estaba esperando, o el dispositivo de E/S esté disponible. Los Jobs se pueden suspender indefinidamente, o por un periodo específico de tiempo (ver sección 5.4.2). Esta es una facilidad sumamente útil del QDOS. En los sistemas antiguos, un programa esperando por E/S puede acaparar todo el tiempo de CPU para intentar transferir pequeñas cantidades de datos.

Inactivo: Son a los que se le ha asignado una prioridad 0 (cero). Los trabajos inactivos no pueden disponer de los recursos de la CPU.

El planificador es invocado, generalmente por una interrupción, 50 veces cada segundo. También se le invoca cuando se activa un trabajo (ver MT.ACTIV). A cada trabajo se le asigna una prioridad temporal. Esta prioridad es incrementada con la prioridad asignada del trabajo en cada llamada del planificador. La prioridad temporal del trabajo que se estaba ejecutando es puesta a cero antes de incrementar todas las prioridades temporales.

Algunos programas que contienen partes críticas, dependientes del tiempo (como leer un sector de microdrive), no deben ser interrumpidas por le planificador. A la rutina que debe terminar en un periodo de tiempo se le llama atómica. La mayoría de las llamadas del sistema son atómicas. Es posible asegurar que una rutina de usuario sea atómica ejecutándola en modo supervisor en el 68008 (pero tenga cuidado de no llamar a una rutina del sistema que sea 'parcialmente' atómica desde una rutina de usuario atómica - El planificador puede entrar en funcionamiento en las rutinas parcialmente atómicas).

3.3 Entrada y salida a Jobs

El QDOS contiene extensas facilidades de comunicación entre trabajos y dispositivos, ya sean estos estándar o expansiones. Teniendo en cuenta que todas las comunicaciones las lleva a cabo el QDOS, no puede haber problemas entre dispositivos. La sección 3.2.1 explica cómo están diseñados los trabajos para una interacción correcta en la asignación de recursos.

Las Entradas y Salidas se manejan con los TRAPS de utilización de E/S (capítulo 7) y con algunas de las utilidades especiales (capítulo 8). Las facilidades de que disponemos son suficientes para la mayoría de las aplicaciones. La pantalla, por ejemplo, se maneja con las rutinas de definición de ventanas, definición de canales de salida en estas ventanas, control de color, tamaño de texto, tipo de cursor, dibujo y rellenado de gráficos, producción de bordes, etc. En caso de que estas rutinas no se acoplen a los requerimientos de un programa particular, es posible incorporar rutinas especiales de usuario que trabajen en conjunción con las del QDOS. El principal criterio a seguir en todas ellas es que el QDOS debe saber en todo momento lo que se está usando, aún en el caso de que no se esté ejecutando una rutina residente del QDOS.

En este punto, los canales pueden ser preparados en una forma estándar que entienda el QDOS. Si se abre o cierra un canal usando un formato estándar (llamado bloque de definición de canal), el QDOS podrá saber lo que se está haciendo.

3.4 Soporte para programas de usuario

El QDOS proporciona vectores a todas sus rutinas, que sirven para supervisar las operaciones del QL. Esta es la principal tarea del QDOS.

La ROM que hay dentro del QL no solamente tiene que ver con las operaciones del sistema. Hay un considerable número de rutinas de utilidad a las que se puede acceder desde el código del usuario. Todas estas rutinas se explican en el capítulo 8.

Probablemente, el que mejor entiende estas utilidades es el intérprete de comandos de BASIC. Este es un Job por derecho propio (y muy especial), pero no es parte esencial del QL. Se pueden ejecutar otros trabajos en ausencia del BASIC. Muchas de las rutinas usadas por el BASIC se pueden usar igualmente por el código del usuario. El paquete aritmético es un buen ejemplo de ello. El ejemplo de la sección 8.5.5 nos lo ilustra, produciendo una función BASIC extra que evalúa SINH de una variable.

Otras rutinas para entrada y salida serie, conversión de números y manejo de microdrives son algunas entre la amplia selección que están documentadas en las últimas partes de este libro.


Anterior Tabla de contenidos Siguiente
El microproceador 68008   Experimentando con QDOS