Sistemas operativos
Conceptos fundamentales y Servicios del Sistema Operativo
- Introducción
- Protección
- Procesos. Tablas de procesos
- Servicios del Sistema Operativo
- Intérprete de comandos
- Estructura de un Sistema Operativo
- Estructura de un Sistema Operativo
- Conclusiones
- Bibliografía
Introducción
Una de las etapas de la evolución de los sistemas operativos fue la multiprogramación o multitarea, esto que trajo consigo que se tuviera en cuenta un grupo de consideraciones a la hora de concebir los mismos. Así fueron surgiendo distintas estructuras en el diseño, cada una con sus características particulares.
Protección
En los primeros sistemas de cómputo que se utilizaron no fue necesario tener en cuenta la problemática de la protección debido a la forma en que se operaban, es decir se ejecutaba sólo un programa y éste estaba en posesión de todos los recursos existentes (en caso de error, solo se afectaba él).
Al desarrollarse los sistemas operativos aún cuando se mantuviera un único programa en memoria (monoprogramación), se comenzaba a compartir recursos. En este caso, el programa y el sistema operativo comparten la memoria. Si ocurriera un funcionamiento erróneo del programa y él sobrescribe el área de memoria del sistema operativo, resulta evidente que existirá un “crash” de éste.
Otro ejemplo simple se puede notar en el caso del procesamiento en lote. Suponga que un programa cae en un lazo infinito de lectura de tarjetas. Es evidente que tomará todas las que les pertenecían y las que le siguen.
El compartir recursos aumenta la utilización eficiente de estos, pero a la vez incrementa las dificultades. Un error en un programa puede afectar a otros trabajos.
En los sistemas operativos que instrumentan la multiprogramación, pueden ocurrir muchas otras situaciones no tan evidentes como las indicadas, por esto éste se debe proteger y a la vez brindar protección a todos los programas que se ejecutan. Todo recurso compartido debe ser protegido, pero al menos deben disponer de esta característica las entradas y salidas, la memoria y la CPU.
La protección de entrada–salida se logra al no permitir que los programas actúen directamente sobre los dispositivos, sino a través de llamadas a los manejadores de dispositivos que forman parte del sistema de operación. De esta forma se puede chequear si la solicitud es correcta o no y evitar que algo vaya mal.
Para evitar que un programa opere directamente con la entrada–salida, las instrucciones correspondientes se declaran como privilegiadas (esto tiene que estar instrumentado en el hardware) y por ello sólo podrán ser utilizadas por parte del sistema operativo.
Lo antes indicado quiere decir que el hardware deberá brindar dualidad en el modo en que los programas se ejecutan. El primero es el modo “kernel” (o monitor, supervisor, sistema, protegido), y el segundo es el modo usuario. El SO correrá en modo protegido (con derecho a usar instrucciones privilegiadas) y todos los demás en modo usuario.
Por supuesto que en la CPU existirá un “bit” que en todo momento indicará el modo en que se está ejecutando. Este se pondrá a 1 ó 0 cada vez que se produzca un cambio entre el SO y otro programa. Es de suponer que las instrucciones que permiten variar este “bit” son privilegiadas.
Da la impresión que con los aspectos antes indicados ya se tiene garantizada la protección de las entradas salidas, pero antes de dar tal afirmación se hace necesario estar seguro que ningún programa usuario pueda ejecutar en modo supervisor. ¿Qué pasaría si a un programa usuario se le permite realizar direccionamientos al área de memoria del sistema operativo y modificar un vector de interrupción? Al ocurrir la interrupción, el hardware pasará la ejecución al modo privilegiado (ya que va a operar el sistema operativo), pero como se cambió el vector de interrupción, nos encontramos que el programa usuario se hace dueño del sistema de cómputo con total impunidad.
Para evitar esta situación y otras similares se impone disponer de un mecanismo de protección de memoria. Es decir, evitar que un programa usuario pueda acceder al área de trabajo del Sistema Operativo. En los sistemas multiprogramados también se tiene que impedir tal acción en el área de otro programa.
La solución a esta problemática requiere que el hardware brinde su ayuda. En un ambiente de monoprogramación es suficiente con la existencia de un registro tope o registro límite que separe el área de trabajo del sistema operativo de la correspondiente al programa usuario.
En este caso, generalmente el sistema operativo se ubica en la parte baja de la memoria y a continuación comenzaría el área del programa usuario. Cada vez que dicho programa realiza un acceso a memoria, el hardware chequea que la dirección referida no sea menor que la contenida en el registro a los efectos de permitirlo. Si se detecta el intento de penetrar en el área no autorizada ocurrirá una trampa invocándose al SO para que decida la situación (generalmente se elimina al que provoca “la ofensa”).
El SO conserva la posibilidad de acceder cualquier posición de memoria (al correr en modo privilegiado el hardware no lo controla). Por supuesto la carga del registro indicado solo se puede hacer en modo “kernel”.

Si el ambiente de trabajo es multiprogramado, un solo registro no basta. En este caso, se requieren dos registros, almacenándose en ellos el límite superior e inferior de memoria que le es permitido acceder al programa que está en ejecución en cada instante de tiempo (su área de trabajo).

Lo antes indicado presupone que cada vez que pasa el control del CPU de un programa a otro, el sistema de operación actualice los registros indicados con los nuevos valores requeridos.
En la actualidad existen otros esquemas de protección de memoria con mayores grados de sofisticación, en la continuación de la asignatura se hará referencia a algunos de ellos.
La protección del procesador tiene como objetivo evitar que un programa usuario caiga en un lazo de procesamiento infinito adueñándose de éste por tiempo indefinido. Esto se logra por medio de un reloj (“timer”) de hardware que permite detener el procesamiento y regresar el control, vía una interrupción, al sistema operativo.
Generalmente se instrumenta un reloj variable por medio de uno fijo y un contador. Dicho contador recibe un valor por parte del sistema operativo y se decrementa con cada golpe del reloj de intervalo fijo, cuando alcanza el valor cero se emite la interrupción y el sistema operativo decide la acción a ejecutar. Por supuesto, las instrucciones que permiten modificar el valor del reloj son privilegiadas.
Procesos. Tablas de procesos
Antes de continuar estudiando otros aspectos relacionados con los sistemas operativos resulta conveniente puntualizar el concepto de proceso que constituye uno de los más esenciales en esta materia.
Un proceso es, básicamente, un programa en ejecución y precisamente por esa razón existe la tendencia a confundir ambos términos. La diferencia consiste en que un proceso incluye además del programa (secuencia de código ejecutable) los datos, la pila, el contador de programa, los valores almacenados en los registros y todo aquello que refleja el estado de la ejecución en un instante.
La importancia de este concepto radica en que un programa por si solo no refleja su estado de ejecución, lo que resulta esencial a los efectos de continuar su procesamiento futuro si en un determinado momento se le retira el control del procesador (lo que constituye la base de la multiprogramación).
Para guardar la información de los procesos que en cada instante están siendo atendidos por el sistema de operación se utiliza la tabla de procesos. Esta no es más que un arreglo o lista de estructuras donde cada una de ellas contiene los datos que definen el estado de un proceso determinado. Las informaciones de un proceso se actualizan en numerosos momentos, pero por lo menos cada vez que se le va a quitar el uso del procesador.
Los campos que componen cada entrada en la tabla de procesos varían de un sistema operativo a otro y generalmente son numerosos. Resultan típicos algunos como: estado del proceso, valores de los registros, contador de programa, identificador, área de memoria utilizada, tabla de ficheros abiertos, directorio actual, etc.
Todo proceso presente en un sistema operativo se identifica por un número entero que se conoce por el identificador del proceso (PID).
Para ver el PID de los procesos que corren en un sistema Windows (nt) Crl+Shift+Esc y en el administrador de tares de Windows en el menú: ver/seleccionar columnas y marcar Identificador de proceso (PID). En Linux: Escribir en una consola ps –A
Generalmente un proceso puede crear uno o más procesos (procesos hijos) que a su vez pueden crear otros, llegándose a una estructura arbórea.
knoppix@ttyp0[knoppix]$ pstree -ah
init
|-automount –pid-file=/var/run/autofs/_:mnt_:auto.pid –timeout=2 /mnt/auto
|-bash -login
|-bash -login
|-bash -login
|-bash -login
|-(bdflush)
|-kalarm -caption KAlarm -icon kalarm
| `-xmms -p
| `-xmms -p
| |-xmms -p
| |-xmms -p
| |-xmms -p
| `-xmms -p
|-kalarmd
|-kdeinit
| |-kdeinit
| |-kdeinit
| |-kdeinit
| |-kdeinit
| `-kdeinit
| `-bash
| `-pstree -ah
|-kdeinit
|-kdeinit
|-kdeinit
|-kdeinit
|-kdeinit
|-kdeinit
|-kdeinit
|-kdeinit
|-kdeinit
|-kdeinit
|-kdesud
|-(keventd)
|-(khubd)
|-kmix
|-knotes
|-krandrtray
|-(ksoftirqd_CPU0)
|-(kswapd)
|-(kupdated)
|-pump -i eth0
`-xsession /etc/init.d/xsession start
|-xinitrc /etc/X11/xinit/xinitrc
| `-kwrapper ksmserver
`-xsession /etc/init.d/xsession start
`-XFree86 -noreset -xf86config /etc/X11/XF86Config-4 -dpi 75: 0
Ejemplo de estructura de procesos en UNIX (Linux).
Servicios del Sistema Operativo
Como ya se indicó, una de las dos funciones principales de un sistema operativo es servir de máquina ampliada o virtual, brindando facilidades a los programas de los usuarios y a estos. Para lograr este objetivo, los sistemas operativos se encargan de programar el trabajo con los diferentes dispositivos existentes en el sistema de cómputo, separando a los usuarios y programas de esta tarea compleja y tediosa.
Los servicios a usuarios se brindan, básicamente, por medio de los llamados Programas del Sistema, mientras que a los programas se les brindan a través de las Llamadas al Sistema.
Los programas del sistema constituyen una colección más o menos grande de programas (no funciones o subrutinas) suministradas por el fabricante (u otra empresa) que permite realizar operaciones que son comunes a diferentes usuarios, brindando un ambiente más adecuado para el desarrollo y explotación de aplicaciones.
Los programas del sistema pueden ser divididos en varias categorías, aunque esto también depende de cada sistema operativo. Algunos posibles grupos serian : Manipulación de ficheros (crear, eliminar, renombrar, imprimir, etc.), obtención de información de estado (fecha, hora, memoria disponible, espacio en disco, etc.), editores de texto, etc.
En resumen, los programas del sistema son aquellos que ejecutan las acciones descritas en los comandos de éste o que aparecen en los menús en el caso de las interfaces gráficas.
Las llamadas al sistema constituyen la interface entre el sistema de operación y los procesos. Estas generalmente se hacen por medio de instrucciones en lenguaje ensamblador, aunque en algunos casos existen facilidades que permiten se realicen desde lenguajes de alto nivel.
En el segundo caso antes indicado, se dan las variantes de que existan funciones o procedimientos predefinidos en biblioteca que realicen las llamadas al sistema como tal (UNIX, Windows) o el compilador genera directamente las instrucciones necesarias para esto.
Los mecanismos que ponen en ejecución las llamadas al sistema operativo difieren de uno a otro:
- ? En el OS/360 existe una instrucción especial (SVC) que provoca una trampa hacia el sistema. El número de la llamada se da en la instrucción.
- ? En el CP/M no existe una instrucción especial y por ello el número de la llamada se pone en el registro C y se salta a la dirección 5 de la memoria.
- ? En MS-DOS se utiliza la instrucción INT seguida de un número de interrupción (21H).
En todos los casos antes indicados, se requiere de la transferencia de parámetros desde o hacía el procedimiento que instrumenta la llamada. Este pase de parámetros se ejecuta a través de los registros del procesador o por medio de un bloque o tabla de memoria (pasándose la dirección en un registro).
El número de llamadas, la forma y tipo de cada una y los posibles agrupamientos de estas dependen de cada sistema de operación en específico, aunque en forma general se pudieran catalogar en 4 grupos:
- ? Control de procesos.
Incluyen operaciones con los procesos tales como: Crear, eliminar, finalizar, abortar, ejecutar, enviar señal, esperar por señal, etc.
- ? Manipulación de ficheros.
Incluyen operaciones con los ficheros tales como: Crear, eliminar, abrir, cerrar, renombrar, leer, escribir, etc.
- ? Manipulación de dispositivos.
Incluyen operaciones con los dispositivos tales como: Solicitar, liberar, leer, escribir, etc.
- ? Intercambio de información.
Incluyen operaciones tales como: Conocer la fecha, conocer la hora, conocer atributos de ficheros, fijar atributos de ficheros, fijar la fecha, etc.
Además de los grupos antes indicados podría haber otros u otras operaciones dentro de estos. Otros conjuntos podrían ser:
- ? Manipulación de directorios y sistemas de ficheros.
- ? Protección.
- ? Señalización.
La mejor manera de entender la esencia de las llamadas al sistema consiste en hacer una revisión detallada de las que están presentes en uno o varios sistemas operativos y por ello se recomienda revisar las páginas de la 23 a la 36 del segundo libro de Tanenbaum, donde se presenta la explicación de las más importantes presentes en la versión 7 del UNIX.
Intérprete de comandos
Uno de los más importantes programas del sistema es el intérprete de comandos. Es el programa que sirve de interface entre el sistema operativo y los usuarios de éste. Aún cuando algunos autores no lo consideran parte del sistema de operación (dado que cada usuario podría crear el suyo), no hay duda que guarda una estrecha relación con éste.
El interprete de comandos toma el control una vez que el sistema operativo ha sido cargado o el control de una terminal una vez que un usuario se ha identificado en un sistema de tiempo compartido.
Los intérpretes de comandos han recibido distintos nombres en diferentes sistemas operativos: interprete de tarjetas de control, intérprete de línea de comando, procesador de comandos de consola (CPM), “Shell” (UNIX), etc.
La función del intérprete de comandos es en general bastante simple y consiste en tomar la tarjeta de control o comando, validar si es correcto o no y en el primer caso realizar la ejecución correspondiente. El código que ejecuta el comando puede formar parte del propio intérprete o constituye otro programa del sistema.
Los intérpretes de comandos que presentan interfaces con usuarios más amigables, incluyendo las, hoy, reconocidas interfaces gráficas, tienen una mayor complejidad dada el uso de menús, botones, “mouse” y otros recursos.
Aún cuando en la mayoría de los sistemas operativos el interprete de comandos pierde el control de ejecución tan pronto se inicia un comando y no lo recupera hasta que éste finalice, hay algunos donde el comando se ejecuta en paralelo (como un proceso hijo del interprete). Un ejemplo de esto está en el UNIX con el uso del símbolo &.
Estructura de un Sistema Operativo
La estructura de un sistema operativo se puede analizar desde el punto de vista funcional y desde el punto de vista organizativo de los programas que lo componen.
Desde el punto de vista funcional hay que tener en cuenta que los sistemas operativos son programas manejados por eventos. Si no hay programa que ejecutar, dispositivo al cual brindar servicio o usuario que atender entonces no hará nada. Los eventos (mensajes o señales) que lo ponen en acción serán las interrupciones o las trampas. Por lo tanto, los sistemas de operación son programas manejados por interrupción.
La naturaleza de los sistemas operativos de ser manejados por interrupción determina su estructura desde el punto de vista funcional.
Cuando una interrupción o trampa ocurre, de inmediato el hardware transfiere el control al sistema operativo. Este preserva el estado del proceso que se ejecutaba y a continuación realiza el tratamiento correspondiente.
Pueden ocurrir tipos diferentes de interrupciones, pero pueden agruparse en tres tipos:
- ? Llamadas al sistema.
- ? Interrupción de un dispositivo.
- ? Un error de programa (detectado por hardware).
Las llamadas al sistema, a estos efectos, pueden dividirse en
- ? Solicitud de terminación normal (realizada por un proceso cuando va a terminar su ejecución).
- ? Solicitud de terminación anormal (realizada al detectarse la existencia de un error).
- ? Solicitud de recursos (si no están disponibles, entonces el proceso deberá esperar).
- ? Solicitud de información de estado (la información es transferida).
- ? Solicitud de entrada/salida.
A los efectos de la acción del sistema operativo los casos 3 y 4 se pueden considerar como iguales (en el libro de Peterson se le llaman solicitudes que no son de entrada/salida).
Teniendo en cuenta lo antes indicado, en la figura 2.4 (página 54) del Peterson se presenta la estructura del sistema operativo desde el punto de vista funcional.
De aquí que un sistema operativo estará compuesto por al menos de: manejadores de dispositivos, atención a interrupciones (“handlers”), un conjunto de subrutinas de llamadas al sistema y el intérprete de comandos o de tarjetas de control. Como es lógico, el sistema de ficheros también estará presente. La mayoría de los sistemas operativos brindan funciones adicionales y por ello habrá complejidades aún mayores.
Desde el punto de vista de la organización de los programas, la estructura de un sistema operativo puede tomar distintas formas. Estas podrían ser:
- Sistemas Monolíticos.
Se caracterizan por la no existencia de estructura. Se escriben como una colección de procedimientos donde cada uno de ellos puede llamar a cualquier otro que le brinde un servicio que necesite. En este caso los procedimientos necesitan tener una interface bien definida en términos de parámetros y resultados.
Aún en esta variante puede existir una pequeña estructura en lo que se refiere a los servicios brindados por las llamadas al sistema.

- Sistemas de Capas.
Se caracterizan por estar organizados como una jerarquía de capas, cada una construida sobre la anterior.
El primer sistema construido en esta forma fue el “THE” a cargo de E. W. Dijkstra y sus alumnos (en 1968). En dicho sistema se consideró la existencia de 6 capas:
0.- Asignación del procesador y multiprogramación.
1.- Administración de memoria y tambor magnético.
2.- Comunicación operador – procesos.
3.- Administración de entrada/salida.
4.- Programas usuarios.
5.- El operador.
Una generalización de este concepto fue aplicada en el sistema operativo MULTICS. Se organizó como una serie de anillos concéntricos, siendo los más internos los de mayor prioridad. Para que un procedimiento de un nivel pueda llamar a otro más interno lo tiene que hacer a través de una llamada al sistema.
- Máquinas Virtuales.
En este esquema, el centro del sistema operativo se ejecuta directamente en el hardware existente y permite el logro de la multiprogramación. Esta, en lugar de ejecutar varios procesos, crea varias máquinas virtuales en una segunda capa. Estas máquinas virtuales son copias exactas del hardware original y por ello cada una de ellas puede ejecutar cualquier sistema operativo que pueda operar en la máquina original.
Este formato es conocido hace tiempo (desde la IBM/360), pero hoy se utiliza para crear máquinas virtuales que permitan ejecutar en un sistema operativo programas preparados en otro (Windows lo utiliza para ejecutar programas de MS-DOS o de versiones anteriores).
- Modelo cliente – servidor.
Es una tendencia de los actuales sistemas de operación que consiste en instrumentar la mayoría de las funciones en procesos usuarios, construyendo un “kernel” mínimo.
Para solicitar un servicio, un proceso usuario (llamado cliente) envía la solicitud al proceso servidor, el cual realiza el trabajo y le regresa la respuesta. En este modelo la función principal del “kernel” consiste en manejar la comunicación entre clientes y servidores (y, lógicamente, la atención a las interrupciones de los dispositivos).
La división del sistema operativo en partes, cada una de las cuales atiende una faceta de éste, ejecutándose la mayoría de ellos (de los servidores) en modo usuario, permite dos ventajas importantes.
La primera consiste en que la aparición de un error en una parte no implica necesariamente que todo el sistema se caiga (que ocurra un “crash”). La segunda consiste en la fácil adaptación de un sistema de este tipo para su utilización en un medio distribuido.

Conclusiones
A modo de conclusión hemos podido ver la importancia que tiene la protección de la información que manejan cada uno de los dispositivos que interactúan con el sistema operativo. Vimos el concepto de proceso y su significado, como hacen las aplicaciones para comunicarse con el SO a través de las llamadas al sistema y que estructura de diseño siguen estos.
