Universidad Nacional del Nordeste Facultad de Ciencias Exactas, Naturales y Agrimensura Trabajo Final de Aplicación “Desarrollo de un Entorno de Aprendizaje de Sistemas Operativos” Laura Cristina Gonzalez - L.U.: 30.470 Prof. Coordinador: Agr. Castor Herrmann Prof. Orientador: Mgter. David Luis la Red Martínez Licenciatura en Sistemas Corrientes - Argentina 2009 A mi Familia, Amigos y Compañeros Prefacio Una de las muchas y muy variadas posibles aplicaciones de la P.O.O. (programación orientada a objetos) está en el desarrollo de algoritmos que implementen estrategias de administración de recursos por parte del Sistema Operativo. Como parte de las estrategias antes mencionadas, podemos considerar las de administración o asignación del procesador, es decir aquéllas según las cuales los S. O. seleccionan a cuál de los procesos listos para ser ejecutados en ejecución concurrente, le asignarán el procesador en un momento dado, es decir, a qué proceso darán la posibilidad de utilizar la CPU para ejecutar sus propias instrucciones; a esta decisión también se la conoce como despacho del proceso. El concepto central de cualquier Sistema Operativo es el de proceso: una abstracción de un programa en ejecución también llamada tarea. En sistemas de multiprogramación la CPU alterna de programa en programa, en un esquema de seudoparalelismo, es decir que la cpu ejecuta en cierto instante un solo programa, intercambiando muy rápidamente entre uno y otro. El paralelismo real de hardware se da en las siguientes situaciones: • En ejecución de instrucciones de programa con más de un procesador de instrucciones en uso simultáneamente. • Con la superposición de ejecución de instrucciones de programa con la ejecución de una o más operaciones de entrada / salida. El objetivo es aumentar el paralelismo en la ejecución. El modelo de procesos posee las siguientes características: • Todo el software ejecutable, inclusive el Sistema Operativo, se organiza en varios procesos secuenciales o procesos. • Un proceso incluye al programa en ejecución y a los valores activos del contador, registros y variables del mismo. • Conceptualmente cada proceso tiene su propia CPU virtual. • Si la CPU alterna entre los procesos, la velocidad a la que ejecuta un proceso no será uniforme. • Un proceso es una actividad de un cierto tipo, que tiene un programa, entrada, salida y estado. • Un solo procesador puede ser compartido entre varios procesos con cierto algoritmo de planificación, el cual determina cuándo detener el trabajo en un proceso y dar servicio a otro distinto. En cuanto a las jerarquías de procesos es necesario señalar que los Sistemas Operativos deben disponer de una forma de crear y destruir procesos cuando se requiera durante la operación, teniendo además presente que los procesos pueden generar procesos hijos mediante llamadas al Sistema Operativo, pudiendo darse ejecución en paralelo. Respecto de los estados del proceso deben efectuarse las siguientes consideraciones: vi • Cada proceso es una entidad independiente pero frecuentemente debe interactuar con otros procesos. • Los procesos pueden bloquearse en su ejecución porque: — Desde el punto de vista lógico no puede continuar porque espera datos que aún no están disponibles. — El Sistema Operativo asignó la CPU a otro proceso. Los estados que puede tener un proceso son 3: • En ejecución: utiliza la CPU en el instante dado. • Listo: ejecutable, se detiene en forma temporal para que se ejecute otro proceso. • Bloqueado: no se puede ejecutar debido a la ocurrencia de algún evento externo. Son posibles cuatro transiciones entre estos estados. Estados de Procesos Durante su existencia un proceso pasa por una serie de estados discretos, siendo varias las circunstancias que pueden hacer que el mismo cambie de estado. Debido a ello se puede establecer una Lista de Listos para los procesos listos y una Lista de Bloqueados para los bloqueados. La Lista de Listos se mantiene en orden prioritario y la Lista de Bloqueados está desordenada, ya que los procesos se desbloquean en el orden en que tienen lugar los eventos que están esperando. Al admitirse un trabajo en el sistema se crea un proceso equivalente y es insertado en la última parte de la Lista de Listos. La asignación de la CPU al primer proceso de la Lista de Listos se denomina Despacho, que es ejecutado por una entidad del Sistema Operativo llamada Despachador. El Bloqueo es la única transición de estado iniciada por el propio proceso del usuario, puesto que las otras transiciones son iniciadas por entidades ajenas al proceso. Los sistemas que administran los procesos deben poder crear, destruir, suspender, reanudar, cambiar la prioridad, bloquear, despertar y despachar un proceso. La creación de un proceso significa: • Dar nombre al proceso. • Insertar un proceso en la lista del sistema de procesos conocidos. • Determinar la prioridad inicial del proceso. • Crear el bloque de control del proceso. • Asignar los recursos iniciales del proceso. Un proceso puede crear un nuevo proceso, en cuyo caso el proceso creador se denomina proceso padre y el proceso creado proceso hijo y se obtiene una estructura jerárquica de procesos. La destrucción de un proceso implica: vii • Borrarlo del sistema. • Devolver sus recursos al sistema. • Purgarlo de todas las listas o tablas del sistema. • Borrar su bloque de control de procesos. Un proceso suspendido no puede proseguir hasta que otro proceso lo reanude. Reanudar (reactivar) un proceso implica reiniciarlo en el punto donde fue suspendido. La destrucción de un proceso puede o no significar la destrucción de los procesos hijos, según el Sistema Operativo. Generalmente se denomina Tabla de Procesos al conjunto de información de control sobre los distintos procesos. Una interrupción es un evento que altera la secuencia en que el procesador ejecuta las instrucciones; es un hecho generado por el hardware del computador. Cuando ocurre una interrupción, el Sistema Operativo: • Obtiene el control. • Salva el estado del proceso interrumpido, generalmente en su bloque de control de procesos. • Analiza la interrupción. • Transfiere el control a la rutina apropiada para la manipulación de la interrupción. Una interrupción puede ser iniciada por un proceso en estado de ejecución o por un evento que puede o no estar relacionado con un proceso en ejecución. Generalmente las interrupciones se pueden clasificar en los siguientes tipos: • SVC (llamada al supervisor): es una petición generada por el usuario para un servicio particular del sistema. • Entrada/Salida: son iniciadas por el hardware de Entrada / Salida. • Externas: son causadas por distintos eventos, por ejemplo, expiración de un cuanto en un reloj de interrupción o recepción de una señal de otro procesador en un sistema multiprocesador. • De reinicio: ocurren al presionar la tecla de reinicio o cuando llega una instrucción de reinicio de otro procesador en un sistema multiprocesador. • De verificación de programa: son causadas por errores producidos durante la ejecución de procesos. Concurrencia e Hilos con Java Los hilos o procesos ligeros son una parte de código o miniprograma que puede ser ejecutada independientemente, de forma que una aplicación o un applet puede tener varios viii hilos ejecutándose simultáneamente y efectuando distintas tareas; estos hilos se encuentran dentro de un programa y son parte de él. Los hilos, a veces también llamados contextos de ejecución, pueden ser utilizados para la implementación de algoritmos paralelos o procesos concurrentes, sin ser necesario disponer de equipos con estructura de multiprocesador. En el caso de un solo procesador, los procesos ligeros incorporan mecanismos para compartirlo, estableciéndose prioridades entre ellos y también facilidades de sincronización, cuando es necesario. Objetivos logrados Se han alcanzado los objetivos planteados para el presente trabajo: • Desarrollo de una página Web empleando para la confeccion de la misma software Dreamweaver . • Desarrollo de Applets empleandoel lenguaje Java y el Netbeans IDe 6.7.1. Etapas de desarrollo Se ha efectuado una amplia recopilación bibliográfica específica a los temas pertinentes a la tarea planificada y a los productos de software que se emplearon para la concreción del trabajo final. Se ha desarrollado el aplicativo con la utilización del lenguaje Java, versión jdk1.5.0-15. En el marco de la herramienta Dreamweaver CS3 se desarrollaron la página web del aplicativo utilizadando páginas HTML. En el marco de la herramienta Netbeans IDE 6.7.1 se desarrollaron los Applets utilizadandos en la página web del aplicativo. Generacion del ejecutable del Sistema desarrollado por el Profesor Orientador Mgter. David Luis la Red Martinez, Concurrencia e Hilos en java Una vez finalizada la etapa de desarrollo se realizaron las siguientes actividades: • Montar la página web en un servidor. • Testear el buen funcionamiento de la página y de los algoritmos desarrollados. Finalizada la aplicación se realizó la grabación en DVD de todo el material correspondiente al trabajo final: una versión de la aplicación, otra referente al libro en formato LaTex y el PDF generado. También se incluyó los instaladores de los productos utilizados para el desarrollo, es decir Netbeans IDE 6.7.1, Dreamweaver CS3,java 6.0 update 11. • Organización del Informe Final El trabajo final de aplicación comprende un informe final impreso y un DVD además de un resúmen y de un resúmen extendido. El informe final está organizado en capítulos los que se indican a continuación: Introducción: Es un breve marco teórico sobre los Sistemas operativos: • Conceptos S.O., estructuras S.O., tendencias S.O. • Definiciones de procesos, estados y planificacion de procesos, niveles de planificacion, etc. ix Java: Se presentan los principales aspectos y características referidas al lenguaje. Heramientas Utilizadas: Se detallan las características más utilizadas tanto en Netbeans IDE 6.7.1 y Dreamweaver CS3. Descripción de la aplicación: Se describen todos los aspectos de la aplicación desarrollada utilizando las herramientas antes mencionadas. Conclusiones: Se presentan las conclusiones a las que se ha llegado al finalizar el presente trabajo. El DVD adjunto al informe final impreso, contiene lo siguiente: • Instaladores del software utilizado. • Resúmenes del trabajo realizado. • Informe final en formato digital. • Presentación para la defensa final. • Aplicación desarrollada. Laura Cristina Gonzalez Licenciatura en Sistemas Universidad Nacional del Nordeste Corrientes; 15 de Diciembre de 2009 x Índice General 1 Introducción 1.1 Qué es un Sistema Operativo . . . . . . . . . 1.2 Historia de los Sistemas Operativos - Generaciones . . 1.3 Conceptos de los Sistemas Operativos . . . 1.4 Estructura de los Sistemas Operativos . . . 1.5 Tendencias . . . . . . . . . . . . . . . . . . . . . . . . 1.6 Definiciones Sobre Procesos . . . . . . . . . . . . . . . 1.7 Estados de Procesos . . . . . . . . . . . . . . . . . . . 1.8 El Núcleo del Sistema Operativo . . . . . . . . . . . . 1.9 Planificación de Procesos . . . . . . . . . . . . . . . . 1.10 Niveles de Planificación del Procesador . . . . . . . . . 1.11 Objetivos de la Planificación . . . . . . . . . . . . . . 1.12 Conceptos Básicos de Almacenamiento Virtual . . . . 1.13 Organización del Almacenamiento de Niveles Múltiples 1.14 Sistemas de Archivos . . . . . . . . . . . . . . . . . . . 1.15 Funciones del Sistema de Archivos . . . . . . . . . . . 1.16 El Sistema de Archivos . . . . . . . . . . . . . . . . . . 1.17 Entrada / Salida . . . . . . . . . . . . . . . . . . . . . 1.18 Algoritmos de Programación del Brazo del Disco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Fundamentos Teóricos 2.1 Procesos y Administración del Procesador . . . . . . . . . . . . . . . 2.1.1 Criterios de Planificación . . . . . . . . . . . . . . . . . . . . 2.2 Planificación Apropiativa Versus No Apropiativa . . . . . . . . . . . 2.3 Temporizador de Intervalos o Reloj de Interrupción . . . . . . . . . . 2.4 Prioridades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Tipos de Planificación . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 Planificación a Plazo Fijo . . . . . . . . . . . . . . . . . . . . 2.5.2 Planificación Garantizada . . . . . . . . . . . . . . . . . . . . 2.5.3 Planificación del Primero en Entrar Primero en Salir (FIFO) 2.5.4 Planificación de Asignación en Rueda (RR: Round Robin) . . 2.5.5 Tamaño del Cuanto o Quantum . . . . . . . . . . . . . . . . . 2.5.6 Planificación del Trabajo Más Corto Primero (SJF) . . . . . 2.5.7 Planificación del Tiempo Restante Más Corto (SRT) . . . . . 2.5.8 Tiene mayor sobrecarga que la planificación SJF. . . . . . . . xi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 3 6 8 12 14 17 18 19 20 21 23 24 25 27 28 29 29 . . . . . . . . . . . . . . 33 33 33 34 35 35 36 36 37 37 37 38 38 39 39 xii ÍNDICE GENERAL 2.6 2.7 2.8 2.9 2.10 2.11 2.12 2.13 2.14 2.15 2.16 2.17 2.18 2.19 2.20 2.5.9 Planificación el Siguiente con Relación de Respuesta Máxima HRN . 2.5.10 Planificación por Prioridad . . . . . . . . . . . . . . . . . . . . . . . 2.5.11 Colas de Retroalimentación de Niveles Múltiples . . . . . . . . . . . 2.5.12 Política Versus Mecanismo de Planificación . . . . . . . . . . . . . . 2.5.13 Planificación de Dos Niveles . . . . . . . . . . . . . . . . . . . . . . . Estrategias de Administración del Almacenamiento Virtual . . . . . . . . . 2.6.1 Estrategias de Reposición de Página . . . . . . . . . . . . . . . . . . 2.6.2 El Principio de Optimización . . . . . . . . . . . . . . . . . . . . . . 2.6.3 Reposición de Página al Azar . . . . . . . . . . . . . . . . . . . . . . 2.6.4 Reposición de Página por el Sistema de Primero en Entrar - Primero en Salir (FIFO) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6.5 Reposición de Página Menos - Recientemente - Usada (LRU) . . . . 2.6.6 Reposición de Página Menos - Frecuentemente - Usada (LFU) . . . 2.6.7 Reposición de Página No Usada - Recientemente (NUR) . . . . . . . 2.6.8 Localidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6.9 Conjuntos de Trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . Paginación por Demanda y Paginación Anticipada . . . . . . . . . . . . . . 2.7.1 Paginación por Demanda . . . . . . . . . . . . . . . . . . . . . . . . 2.7.2 Paginación Anticipada . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.3 Tamaño de Página . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.4 Comportamiento de un Programa en la Paginación . . . . . . . . . . Porqué es Necesaria la Planificación de Discos . . . . . . . . . . . . . . . . . 2.8.1 Características Deseables de las Políticas de Planificación de Discos Algoritmos de Programación del Brazo del Disco . . . . . . . . . . . . . . . Optimización de la Búsqueda en Discos . . . . . . . . . . . . . . . . . . . . 2.10.1 Planificación FCFS (Primero en Llegar, Primero en Ser Servido) . . 2.10.2 Planificación SSTF (Menor Tiempo de Búsqueda Primero) . . . . . 2.10.3 Planificación SCAN . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.10.4 Planificación SCAN de N - Pasos . . . . . . . . . . . . . . . . . . . . 2.10.5 Planificación C - SCAN (Búsqueda Circular) . . . . . . . . . . . . . 2.10.6 Esquema Eschenbach . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.10.7 Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Optimización Rotacional en Discos . . . . . . . . . . . . . . . . . . . . . . . Consideraciones de los Discos Sobre los Sistemas . . . . . . . . . . . . . . . Manejo de Errores en Discos . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.13.1 Ocultamiento de Una Pista a la Vez en Discos . . . . . . . . . . . . Discos en RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Relojes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Terminales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Procesos y Procesadores en Sistemas Distribuidos . . . . . . . . . . . . . . . Introducción a los Hilos (Threads) . . . . . . . . . . . . . . . . . . . . . . . 2.18.1 Uso de Hilos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.18.2 Aspectos del Diseño de un Paquete de Hilos . . . . . . . . . . . . . . Implantación de un Paquete de Hilos . . . . . . . . . . . . . . . . . . . . . . Hilos y RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 39 40 41 41 43 44 44 44 45 45 46 46 47 48 51 51 51 51 53 53 55 56 59 59 59 60 60 60 60 60 61 61 62 63 64 64 65 67 67 68 69 70 72 ÍNDICE GENERAL xiii 3 JAVA 3.1 Introducción al Lenguaje . . . . . . . . . . . . . . 3.1.1 Bibliotecas de Clases Estándares de Java 3.1.2 Java es Multiplataforma . . . . . . . . . . 3.1.3 Características del Lenguaje Java . . . . . 3.2 Estructura General de un Programa Java . . . . 3.3 Conceptos Básicos . . . . . . . . . . . . . . . . . 3.3.1 Clase . . . . . . . . . . . . . . . . . . . . 3.3.2 Herencia . . . . . . . . . . . . . . . . . . . 3.3.3 3.3.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 73 74 74 75 76 77 77 78 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 . . . . . . . . . . . . . . . . . . . . . . . . 79 79 81 82 3.5.1 Operadores Aritméticos . . . . . . . . . . . . . . . . . . . . 3.5.2 Operadores de Asignación . . . . . . . . . . . . . . . . . . . 3.5.3 Operadores Unarios . . . . . . . . . . . . . . . . . . . . . . 3.5.4 Operadores Incrementales . . . . . . . . . . . . . . . . . . . 3.5.5 Operadores Relacionales . . . . . . . . . . . . . . . . . . . . 3.5.6 Operador de Concatenación de Cadenas de Caracteres (+) 3.5.7 Precedencia de Operadores . . . . . . . . . . . . . . . . . . Estructuras de Programación . . . . . . . . . . . . . . . . . . . . . 3.6.1 Sentencias o Expresiones . . . . . . . . . . . . . . . . . . . . 3.6.2 Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6.3 Bifurcaciones . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6.4 Bucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Clases en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.7.1 Características Importantes de las Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 82 82 83 83 84 84 85 85 86 86 87 89 90 3.7.2 Métodos o Funciones Miembros . . . . . . . . . . . . . . . . . . . . Algunas Clases de Utilidad . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8.1 Clase Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8.2 Clases String y StringBuffer . . . . . . . . . . . . . . . . . . . . . . 3.8.3 Clase Double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8.4 Clase Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.9 El AWT (Abstract Windows Toolkit) . . . . . . . . . . . . . . . . . . . . . 3.9.1 Qué es el AWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.9.2 Creación de una Interface Gráfica de Usuario . . . . . . . . . . . . 3.9.3 Objetos “event source” y Objetos “event listener” . . . . . . . . . 3.9.4 Proceso a Seguir Para Crear Una Aplicación Interactiva (Orientada a Eventos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10 Errores Frecuentes de Programación . . . . . . . . . . . . . . . . . . . . . 3.10.1 Scheduling de Hilos de Ejecución . . . . . . . . . . . . . . . . . . . 3.10.2 Errores en el Uso de las Características de Portabilidad de Java . . 3.10.3 Uso de Directorios Definidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 92 92 93 93 94 94 94 94 95 . . . . . 95 96 96 97 98 3.4 3.5 3.6 3.7 3.8 3.3.5 La Jerarquía de Clases de Java (API) Variables Dentro del Lenguaje Java . . . . . . 3.4.1 Visibilidad y Vida de las Variables . . Operadores en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv ÍNDICE GENERAL 3.11 3.12 3.13 3.14 3.15 3.16 3.10.4 Carga de Drivers JDBC . . . . . . . . . . . . . . . . 3.10.5 Terminación de Líneas . . . . . . . . . . . . . . . . . 3.10.6 Entrada/Salida por Archivo . . . . . . . . . . . . . . 3.10.7 Fuentes de Caracteres . . . . . . . . . . . . . . . . . APPLETS . . . . . . . . . . . . . . . . . . . . . . . . . . . . QUÉ ES UN APPLET . . . . . . . . . . . . . . . . . . . . 3.12.1 Algunas características de las applets . . . . . . . . 3.12.2 Métodos que controlan la ejecución de un applet . . 3.12.3 Métodos para dibujar el applet . . . . . . . . . . . . CÓMO INCLUIR UN APPLET EN UNA PÁGINA HTML PASO DE PARÁMETROS A UN APPLET . . . . . . . . . CARGA DE APPLETS . . . . . . . . . . . . . . . . . . . . 3.15.1 Localización de ficheros . . . . . . . . . . . . . . . . 3.15.2 Archivos JAR (Java Archives) . . . . . . . . . . . . APPLETS QUE TAMBIÉN SON APLICACIONES . . . . 4 Herramientas utilizadas 4.1 Netbeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 La Plataforma NetBeans . . . . . . . . . . . . . . . . 4.2 NetBeans IDE . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Creación de proyecto . . . . . . . . . . . . . . . . . . . . . 4.4 Creación de un Package . . . . . . . . . . . . . . . . . . . . 4.5 Creación del applet . . . . . . . . . . . . . . . . . . . . . . . 4.6 Creación de la página HTML . . . . . . . . . . . . . . . . . 4.7 Ejecución de un Applets . . . . . . . . . . . . . . . . . . . . 4.8 Como crear un archivo jar con Netbeans . . . . . . . . . . . 4.9 Adobe Dreamweaver CS3 . . . . . . . . . . . . . . . . . . . 4.9.1 Qué es Dreamweaver CS3? . . . . . . . . . . . . . . 4.9.2 Novedades de Dreamweaver CS3 . . . . . . . . . . . 4.10 Entorno de trabajo . . . . . . . . . . . . . . . . . . . . . . . 4.10.1 Pantalla Principal . . . . . . . . . . . . . . . . . . . 4.10.2 La barra de título . . . . . . . . . . . . . . . . . . . 4.10.3 La barra de menús . . . . . . . . . . . . . . . . . . . 4.10.4 La barra de herramientas estándar . . . . . . . . . . 4.10.5 La barra de herramientas de documento . . . . . . . 4.10.6 La barra de estado . . . . . . . . . . . . . . . . . . . 4.10.7 Los paneles e inspectores . . . . . . . . . . . . . . . 4.10.8 El inspector de Propiedades . . . . . . . . . . . . . . 4.10.9 La barra de herramientas Insertar o panel de objetos 4.10.10 Vistas de un documento . . . . . . . . . . . . . . . . 4.10.11 La vista de Diseño . . . . . . . . . . . . . . . . . . . 4.10.12 La vista código . . . . . . . . . . . . . . . . . . . . . 4.10.13 La vista Código y Diseño . . . . . . . . . . . . . . . 4.11 Como crear un página HTML con Dreamweaver CS3 . . . . 4.11.1 Propiedades de la página. . . . . . . . . . . . . . . . 4.11.2 Insertar una imagen con Dreamweaver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 100 101 101 101 101 102 103 104 104 105 105 105 105 106 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 . 109 . 109 . 110 . 110 . 112 . 112 . 115 . 116 . 116 . 122 . 122 . 122 . 125 . 125 . 125 . 127 . 127 . 127 . 127 . 128 . 128 . 128 . 128 . 130 . 130 . 130 . 133 . 134 . 135 ÍNDICE GENERAL xv 4.11.3 Insertar un Vinculo . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 4.11.4 Vista previa del HTML . . . . . . . . . . . . . . . . . . . . . . . . . 137 5 Algoritmos de Planificación del Procesador 143 5.1 Como montar la página web al servidor . . . . . . . . . . . . . . . . . . . . 145 6 Conclusión 159 Bibliografía 161 Índice de Materias 163 Índice de Figuras 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 Recursos administrados por el S. O. . . . . . . . . . . . . . . . . . . . . . Modelo de estructura simple para un sistema monolítico. . . . . . . . . . . Forma de llamada al sistema en un sistema monolítico. . . . . . . . . . . . La estructura de VM/370 con CMS. . . . . . . . . . . . . . . . . . . . . . El modelo cliente - servidor. . . . . . . . . . . . . . . . . . . . . . . . . . . El modelo cliente - servidor en un sistema distribuido. . . . . . . . . . . . Multiprogramación de cuatro programas. . . . . . . . . . . . . . . . . . . Solo un programa está activo en un momento dado. . . . . . . . . . . . . Un proceso puede estar en ejecución, bloqueado o listo. . . . . . . . . . . Niveles de planificación del procesador. . . . . . . . . . . . . . . . . . . . . Transformación de ítems del espacio de direcciones virtuales al espacio de direcciones reales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.12 Contigüidad artificial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.13 Almacenamiento de dos niveles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 9 9 12 13 13 16 16 17 21 . 24 . 25 . 26 2.1 2.2 2.3 2.4 2.5 2.6 2.7 Tipos de planificación del procesador . . . . . . . . . . . . . . . . . . . . . . Ejemplo de anomalía de FIFO. . . . . . . . . . . . . . . . . . . . . . . . . . Fenómeno de localidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Una definición del conjunto de trabajo de páginas de un proceso. . . . . . . Tamaño del conjunto de trabajo como una función del tamaño de la ventana. Producto espacio - tiempo con paginación por demanda. . . . . . . . . . . . Comportamiento de un programa en la paginación. . . . . . . . . . . . . . . 3.1 Jerarquia de Clases de Applets . . . . . . . . . . . . . . . . . . . . . . . . . 102 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 Nuevo proyecto . . . . . . . Nuevo proyecto paso 2 . . . Nuevo proyecto paso 3 . . . Creando un paquete . . . . Creacion de paquete paso 2 Creacion del applet paso 1 . Creacion del applets paso 2 Creaccion de applet paso 3 Creacion del HTML paso 1 Creacion del HTML paso 2 Creacion del HTML paso 3 Ejecutar un Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 45 49 50 50 52 54 111 111 112 113 114 115 116 117 118 119 119 120 xviii ÍNDICE DE FIGURAS 4.13 4.14 4.15 4.16 4.17 4.18 4.19 4.20 4.21 4.22 4.23 4.24 4.25 4.26 4.27 4.28 4.29 4.30 4.31 4.32 4.33 4.34 4.35 4.36 4.37 4.38 4.39 4.40 4.41 4.42 Visualizando el applet en el appletviewer . . . . . . Propiedades de un proyecto . . . . . . . . . . . . . Propiedades del Proyecto . . . . . . . . . . . . . . Generar un archivo jar-Clean and Build . . . . . . Outup del proyecto al generar el archivo jar . . . . Proyecto - dist -Hilos.jar . . . . . . . . . . . . . . . Pantalla principal del Dreamweaver Cs3 . . . . . . Barra de menues . . . . . . . . . . . . . . . . . . . Barra de Herramientas estándart . . . . . . . . . . Barra de herramienta del documento . . . . . . . . Barra de Estado . . . . . . . . . . . . . . . . . . . Panel de inspector de propiedades . . . . . . . . . Barra de herramientas Insertar o Panel de objetos Barra de herramienta del documento . . . . . . . . Vista de Diseño Dreamweaver . . . . . . . . . . . . Vista de código en Dreamweaver . . . . . . . . . . Vista de diseño y codigo . . . . . . . . . . . . . . . Nuevo Documento HTML . . . . . . . . . . . . . . Ventana de Bienvenida del Dramweaver . . . . . . Documento Html sin titulo. . . . . . . . . . . . . . Ventana de Guardar Como. . . . . . . . . . . . . . Propiedades de la página HTML . . . . . . . . . . Configuración de las propiedades de la página . . . Paleta de Colores de Fondo del la página . . . . . . Tamaño y tipo de fuente de la página . . . . . . . Insertar -Barra de herramientas . . . . . . . . . . . Insertar una imagen . . . . . . . . . . . . . . . . . Insertar un Hyperlink desde el menu. . . . . . . . . Configuracion Hyperlik . . . . . . . . . . . . . . . . Seleccionar archivo para el enlace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 121 122 123 123 124 126 127 127 127 128 128 129 129 130 131 132 133 134 135 136 137 137 138 138 139 139 140 140 141 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 5.12 5.13 5.14 5.15 Barra de dirección del navegador . . . . . . . . . . . . . . . Página Principal . . . . . . . . . . . . . . . . . . . . . . . . Botón de Algortimo de Planificacion de Procesos . . . . . . Página de los Algoritmos . . . . . . . . . . . . . . . . . . . . Algoritmo de Planificacion F.I.F.O. . . . . . . . . . . . . . . Cuadro de entrada de cantidad de procesos . . . . . . . . . Cuadro de entrada del tiempo de los procesos. . . . . . . . . Resultado del Algoritmo Fifo . . . . . . . . . . . . . . . . . Botón Hilos de Java . . . . . . . . . . . . . . . . . . . . . . Página de Hilos de java . . . . . . . . . . . . . . . . . . . . Abriendo ejecutable de Hilos en Java . . . . . . . . . . . . . Cuadro de Dialogo con navegador Explorer . . . . . . . . . Cuadro Guardar Como . . . . . . . . . . . . . . . . . . . . . Ventana principal . . . . . . . . . . . . . . . . . . . . . . . Menú Configuración y Ejecución ->Datos de Configuración. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 144 144 145 146 146 147 147 148 148 149 149 150 150 151 ÍNDICE DE FIGURAS 5.16 5.17 5.18 5.19 5.20 5.21 5.22 5.23 5.24 5.25 Ventana de Configuración . . . . . . . . . . . . . . . . . . . . . . . Ventana de Carga de Datos. . . . . . . . . . . . . . . . . . . . . . . Menú Configuración y Ejecución -> Ejecución Concurrente e Hilos Ventana Realizar Ejecución Concurrente e Hilos. . . . . . . . . . . Ventana Lista de Resultados de Ejecución Concurrente e Hilos. . . Ventana Principal-Menú Salir . . . . . . . . . . . . . . . . . . . . . Ventana Principal Tunnelier . . . . . . . . . . . . . . . . . . . . . . Cuadro de Verificacin del HOST . . . . . . . . . . . . . . . . . . . Ventana de Local File y Remote File . . . . . . . . . . . . . . . . . Ventana Local File y Remote File pasando los archivos. . . . . . . xix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 152 152 153 154 154 155 156 156 157 Índice de Tablas 1.1 1.2 Estructura del S.O. en capas “THE”. . . . . . . . . . . . . . . . . . . . . . . 10 Criterios de un buen algoritmo de planificación. . . . . . . . . . . . . . . . . 20 2.1 2.2 Criterios de un buen algoritmo de planificación. . . . . . . . . . . . . . . . . 34 Tipos de prioridades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.1 3.2 3.3 3.4 3.5 3.6 Tipos de Variables. . . . . . . . Categorías de Variables. . . . . Tipos Primitivos de Variables. . Operadores de asignación. . . . Operadores relacionales. . . . . Precedencia de Operadores. . . . . . . . . . . . . . . . . . . . . xxi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 81 81 83 84 85 Capítulo 1 Introducción 1.1 Qué es un Sistema Operativo Una de las definiciones más comúnmente aceptadas expresa: • “Un S. O. es un grupo de programas de proceso con las rutinas de control necesarias para mantener continuamente operativos dichos programas”. El objetivo primario de un Sistema Operativo es [5, la Red Martinez]: • Optimizar todos los rcursos del sistemapara soportar los requerimientos. A los efectos de situar a los S. O. en el conjunto del software para computadoras, podemos clasificar a este de la siguiente manera: • Programas de sistema: — Controlan la operación de la computadora en sí. • Programas de aplicación: — Resuelven problemas para los usuarios. En este contexto, el Sistema Operativo es el programa fundamental de todos los programas de sistema. El S. O. protege y libera a los programadores de la complejidad del hardware, colocándose un nivel de software por sobre el hardware para: • Controlar todas las partes del sistema. • Presentar al usuario una interfaz o maquina virtual . El esquema típico de un sistema de cómputos incluye: • Programas de aplicación: 1 2 CAPÍTULO 1. INTRODUCCIÓN — Sistema bancario, reservaciones en una línea aérea, juegos, etc. • Programas de sistema: — Compiladores, editores, intérpretes de comandos. — Sistema Operativo. • Hardware: — Lenguaje de máquina. — Microprogramación. — Dispositivos físicos Las principales características del microprograma son: • Se trata de software que generalmente se localiza en la memoria de solo lectura. • Busca las instrucciones de lenguaje de máquina para ejecutarlas como una serie de pequeños pasos. • El conjunto de instrucciones que interpreta define al lenguaje de máquina. • En ciertas máquinas se implanta en el hardware y no es en realidad una capa distinta. Respecto del lenguaje de máquina es preciso señalar que: • Generalmente posee entre 50 y 300 instrucciones, sirviendo la mayoría para desplazar datos, hacer operaciones aritméticas y comparar valores. • Los dispositivos de e / s (entrada / salida) se controlan al cargar valores en registros del dispositivo especiales. Una de las principales funciones del S. O. es ocultar toda esta complejidad y brindar al programador un conjunto mas conveniente de instrucciones para trabajar. El S. O. se ejecuta en modo central o modo de supervisión, con máxima prioridad y generalmente con protección por hardware. Los compiladores, editores y demás programas se ejecutan en modo usuario. El S. O. es la serie de programas, dispuestos ya sea en el software o en la memoria fija (microcódigo), que hacen al hardware utilizable. Los S. O. ponen el “poder computacional básico” del hardware convenientemente a disposición del usuario, pero consumen parte de ese poder computacional para funcionar [4, Deitel]. Los S. O. son, en primer lugar, administradores de recursos, siendo el recurso primario el hardware del sistema.1 Las principales características de los S. O. son: • Definir la “Interfaz del Usuario”. 1 Ver Figura 1.1 de la página 4. 1.2. HISTORIA DE LOS SISTEMAS OPERATIVOS - GENERACIONES 3 • Compartir el hardware entre usuarios. • Permitir a los usuarios compartir los datos entre ellos. • Planificar recursos entre usuarios. • Facilitar la entrada / salida. • Recuperarse de los errores. Los principales recursos administrados por los S. O. son: • Procesadores. • Almacenamiento. • Dispositivos de e / s. • Datos. Los S. O. son una interfaz con: • Operadores. • Programadores de aplicaciones. • Programadores de sistemas (administradores del S. O.). • Programas. • Hardware. • Usuarios. El S. O. debe presentar al usuario el equivalente de una máquina extendida o máquina virtual que sea mas fácil de programar que el hardware subyacente. 1.2 Historia de los Sistemas Operativos - Generaciones Los S. O. han estado relacionados históricamente con la arquitectura de las computadoras en las cuales se ejecutan, razón por la cual su historia puede analizarse según las siguientes generaciones y sus principales características [4, Deitel]: • Generación Cero (década de 1940): — Carencia total de S. O. — Completo acceso al lenguaje de máquina. • Primera generación (1945-1955): bulbos y conexiones: — Carencia de S. O. 4 CAPÍTULO 1. INTRODUCCIÓN Figura 1.1: Recursos administrados por el S. O. 1.2. HISTORIA DE LOS SISTEMAS OPERATIVOS - GENERACIONES 5 — En los años cincuenta comienzan como transición entre trabajos, haciendo la misma más simple. • Segunda generación (1955-1965): transistores y sistemas de procesamiento por lotes (batch): — En los años sesenta aparecen los S. O. para sistemas compartidos con: ∗ Multiprogramación: varios programas de usuarios se encuentran al mismo tiempo en el almacenamiento principal, cambiando el procesador rápidamente de un trabajo a otro. ∗ Multiprocesamiento: varios procesadores se utilizan en un mismo sistema para incrementar el poder de procesamiento. — Posteriormente aparece la independencia de dispositivo: ∗ El programa del usuario especifica las características de los dispositivos que requieren los archivos. ∗ El S. O. asigna los dispositivos correspondientes según los requerimientos y las disponibilidades. • Tercera generación (1965-1980): circuitos integrados y multiprogramación: — Difusión de la multiprogramación: ∗ Partición de la memoria en porciones, con trabajos distintos en cada una de ellas. ∗ Aprovechamiento del tiempo de espera consecuencia de operaciones de e / s, para utilizar la CPU para otros procesos. — Protección por hardware del contenido de cada partición de memoria. — Aparición de técnicas de spooling: ∗ Simultaneous Peripheral Operation On Line: operación simultánea y en línea de periféricos. ∗ Almacenamiento de trabajos de entrada y de salida en dispositivos transitorios rápidos (discos), para disminuir el impacto de los periféricos mas lentos. — Son sistemas de modos múltiples, es decir que deben soportar sistemas de propósitos generales; son grandes y complejos pero muy poderosos. — Interponen una capa de software entre el usuario y el hardware. — Aparecen los lenguajes de control de trabajos, necesarios para especificar el trabajo y los recursos requeridos. — Soportan timesharing (tiempo compartido), variante de la multiprogramación con usuarios conectados mediante terminales en línea, permitiendo la operación en modo interactivo o conversacional. — Aparecen los sistemas de tiempo real, que requieren tiempos de respuesta muy exigentes, especialmente para usos industriales o militares. 6 CAPÍTULO 1. INTRODUCCIÓN — Se difunden las computadoras de rango medio. • Cuarta generación (1980-1990): computadoras personales: — Aparición de software amigable con el usuario, destinado a usuarios no profesionales y con una interfase gráfica muy desarrollada. — Desarrollo de sistemas operativos de red y sistemas operativos distribuidos. — Sistemas operativos de red: ∗ Los usuarios están conscientes de la existencia de varias computadoras conectadas. ∗ Cada máquina ejecuta su propio S. O. local. ∗ Son similares a los S. O. de un solo procesador pero con el agregado de: · Controlador de interfaz de la red y su software de bajo nivel. · Software para conexión y acceso a archivos remotos, etc. — Sistemas operativos distribuidos: ∗ Aparece ante los usuarios como un S. O. de un solo procesador, aún cuando de soporte a varios procesadores. ∗ Los usuarios no son conscientes del lugar donde se ejecutan sus programas o donde se encuentran sus archivos, ya que lo debe administrar el S. O. automáticamente. ∗ Deben permitir que un programa se ejecute mediante varios procesadores a la vez, maximizando el paralelismo. — Aparición de emuladores de terminal para el acceso a equipos remotos desde computadoras personales (PC). — Gran énfasis en la seguridad, en especial por el desarrollo de los sistemas de comunicaciones de datos. — El S. O. crea un ambiente de trabajo según el concepto de máquina virtual, que lo aísla del funcionamiento interno de la máquina. — Proliferación de sistemas de bases de datos, accesibles mediante redes de comunicación. 1.3 Conceptos de los Sistemas Operativos La interfaz entre el S. O. y los programas del usuario se define como el conjunto de “instrucciones ampliadas” [10, Tanenbaum] que proporciona el S. O. y son las “llamadas al sistema”: — Crean, eliminan y utilizan objetos del software controlados por el S. O.: ∗ Los mas importantes son procesos y archivos. • Procesos: 1.3. CONCEPTOS DE LOS SISTEMAS OPERATIVOS 7 — Es el concepto central de todos los S. O. — Es básicamente un programa en ejecución. — Consta del programa ejecutable, sus datos y pila, contador y otros registros, además de la información necesaria para ejecutar el programa. — La información de control relacionada con los procesos se almacena en la tabla de procesos: ∗ Es administrada por el S. O. ∗ Posee un arreglo de estructuras, una por cada proceso existente en ese momento. — Un proceso (suspendido) consta de: ∗ Un espacio de dirección. ∗ Los datos pertinentes de la tabla de procesos. — Un proceso puede crear procesos hijo y estos nuevos procesos hijo, conformando un árbol de procesos. • Archivos: — Una de las funciones principales del S. O. es brindar independencia de dispositivo. — Muchos S. O. soportan el concepto de directorio como una forma de agrupar archivos. — Los directorios se estructuran jerárquicamente, por lo que a cada archivo le corresponde una ruta de acceso. — Existen distintos esquemas de seguridad de archivos en los distintos S. O. • Llamadas al sistema: — Permiten a los programas comunicarse con el S. O. y solicitarle servicios. — A cada llamada le corresponde un procedimiento: ∗ Pone los parámetros de la llamada en un lugar específico para luego ejecutar una instrucción tipo “trap” de llamada a procedimiento protegido para iniciar el S. O. ∗ Luego de “trap” el S. O. recupera el control , examina los parámetros y si son válidos ejecuta el trabajo solicitado. ∗ Luego de terminar, el S. O. coloca un código de estado en un registro indicando si tuvo éxito o fracaso y ejecuta una instrucción del tipo “return from trap” para regresar el control al procedimiento. ∗ El procedimiento regresa al programa llamador con un código de estado como un valor de función; dentro de los parámetros pueden regresar valores adicionales. 8 CAPÍTULO 1. INTRODUCCIÓN 1.4 Estructura de los Sistemas Operativos Se considera la organización interna de los S. O. y conforme a ella se los clasifica de la siguiente manera, destacándose sus principales características: • Sistemas monoliticos: — Es muy común: no existe estructura propiamente dicha o es mínima. — El S. O. es una colección de procedimientos que se pueden llamar entre sí.2 — Cada procedimiento tiene una interfaz bien definida en términos de parámetros y resultados. — Para ejecutar los servicios del S. O. (llamadas al sistema):3 ∗ Se solicitan colocando los parámetros en lugares bien definidos (registros o pilas). ∗ Se ejecuta una instrucción especial de trampa: llamada al núcleo o llamada al supervisor. ∗ La instrucción cambia la máquina del modo usuario al modo núcleo (o modo supervisor). [10, Tanenbaum] ∗ Se transfiere el control al S. O. ∗ El S. O. examina los parámetros de la llamada para determinar cuál de ellas se desea realizar. ∗ El S. O. analiza una tabla que contiene en la entrada “k” un apuntador al procedimiento que realiza la “k-ésima” llamada al sistema: · Identifica al procedimiento de servicio llamado. ∗ La llamada al sistema termina y el control regresa al programa del usuario. • Sistemas con capas: — Es una generalización del modelo de estructura simple para un sistema monolítico. — Consiste en organizar el s. o. como una jerarquía de capas, cada una construida sobre la inmediata inferior. — El primer sistema con este esquema fue el “THE” (Holanda - Dijkstra -1968):4 ∗ “THE”: Technische Hogeschool Eindhoven. ∗ Capa 0: · Trabaja con la asignación del procesador. · Alterna entre los procesos cuando ocurren las interrupciones o expiran los cronómetros. 2 Ver Figura 3.1 de la página 102 [10, Tanenbaum]. Ver Figura 1.3 de la página 9 [10, Tanenbaum]. 4 Ver Tabla 1.1 de la página 10 [10, Tanenbaum]. 3 1.4. ESTRUCTURA DE LOS SISTEMAS OPERATIVOS PROG. DEL USUARIO E N M OD O USUARIO PROGRAMA 2 DEL USUARIO M EM OR IA PRINCIPAL 9 PROGRAMA 1 DEL USUARIO LLAMADA AL NUCLEO SIST. OPER. EN MODO N U C LE O 4 PROC. DE SERVICIO 3 1 2 Figura 1.2: Modelo de estructura simple para un sistema monolítico. PROCED. PRINCIPAL PROC. DE SERVICIO PROCED. UTILITARIOS Figura 1.3: Forma de llamada al sistema en un sistema monolítico. 10 CAPÍTULO 1. INTRODUCCIÓN 5 - Operador 4 - Programas del Usuario 3 - Control de Entrada / Salida 2 - Comunicaciones Operador - Proceso 1 - Administración de la Memoria y del Disco 0 - Asignación del Procesador y Multiprogramación Tabla 1.1: Estructura del S.O. en capas “THE”. · Proporciona la multiprogramación básica. ∗ Capa 1: · Administra la memoria. · Asegura que las páginas (porciones de memoria) requeridas de los procesos lleguen a memoria cuando fueran necesarias. ∗ Capa 2: · Administra la comunicación entre cada proceso y la consola del operador. · Por sobre esta capa, cada proceso tiene su propia consola de operador. ∗ Capa 3: · Controla los dispositivos de e / s y almacena en buffers los flujos de información entre ellos. · Por sobre la capa 3 cada proceso puede trabajar con dispositivos abstractos de e / s en vez de con dispositivos reales. ∗ Capa 4: · Aloja los programas del usuario. · Los programas. del usuario no tienen que preocuparse por el proceso, memoria, consola o control de e / s. ∗ Capa 5: · Localiza el proceso operador del sistema. — Una generalización mas avanzada del concepto de capas se presento con “Multics” (MIT, Bell Labs y General Electric): ∗ “Multics”: multiplexed information and computing service. ∗ Presenta una estructura en anillos concéntricos, siendo los interiores los privilegiados. ∗ Un procedimiento de un anillo exterior, para llamar a un procedimiento de un anillo interior, debe hacer el equivalente a una llamada al sistema. • Máquinas virtuales: — Se separan totalmente las funciones de multiprogramación y de máquina extendida. 1.4. ESTRUCTURA DE LOS SISTEMAS OPERATIVOS 11 — Existe un elemento central llamado monitor de la máquina virtual que: ∗ Se ejecuta en el hardware. ∗ Realiza la multiprogramación. ∗ Proporciona varias máquinas virtuales a la capa superior. — Las máquinas virtuales instrumentan copias “exactas” del hardware simple, con su modo núcleo / usuario, e / s, interrupciones y todo lo demás que posee una máquina real. — Pueden ejecutar cualquier S. O. que se ejecute en forma directa sobre el hardware. — Las distintas máquinas virtuales pueden ejecutar distintos S. O. y en general así lo hacen. — Soportan periféricos virtuales. — Ejemplo de S. O. representativo de esta estructura: “VM/370” de IBM:5 ∗ Las m. v. generalmente utilizaran, entre otros, el S. O. “CMS”: Conversational Monitor System. ∗ Cuando un programa “CMS” ejecuta una llamada al sistema: · La llamada es atrapada por el S. O. en su propia m. v.; no pasa directamente al “VM/370”. · “CMS” proporciona las instrucciones de e / s en hardware para la lectura del disco virtual o lo necesario para efectuar la llamada. · “VM/370” atrapa estas instrucciones de e / s y las ejecuta sobre el hardware verdadero. • Modelo cliente - servidor: — Una tendencia en los S. O. modernos es la de explotar la idea de mover el código a capas superiores y mantener un núcleo mínimo, de manera similar al “VM/370”. — Implantar la mayoría de las funciones del S. O. en los procesos del usuario. — Para solicitar un servicio (por ej.: lectura de un bloque de cierto archivo) según el modelo cliente - servidor:6 ∗ El proceso del usuario (proceso cliente) envía la solicitud a un proceso servidor: · Realiza el trabajo y regresa la respuesta. — El núcleo controla la comunicación entre los clientes y los servidores. — Se fracciona el S. O. en partes, cada una controlando una faceta: ∗ Servicio a archivos, a procesos, a terminales, a memoria, etc., cada parte pequeña y más fácilmente controlable. 5 6 Ver Figura 1.4 de la página 12 [10, Tanenbaum]. Ver Figura 1.5 de la página 13 [10, Tanenbaum]. 12 CAPÍTULO 1. INTRODUCCIÓN MAQUINAS 370 VIRTUALES LLAMADA AL SISTEMA AQUI INSTRUC. DE E / S AQUI CMS CMS CMS TRAMPA AQUI VM / 370 TRAMPAS AQUI 370 HARDWARE SIMPLE Figura 1.4: La estructura de VM/370 con CMS. — Los servidores se ejecutan como procesos en modo usuario: ∗ No tienen acceso directo al hardware. ∗ Se aíslan y acotan más fácilmente los problemas. — Se adapta para su uso en los sistemas distribuidos:7 ∗ Si un cliente se comunica con un servidor mediante mensajes: · No necesita saber si el mensaje se atiende localmente o mediante un servidor remoto, situado en otra máquina conectada. · Envía una solicitud y obtiene una respuesta. — Algunas funciones del S. O., por ej. el cargado de comandos en los registros físicos del dispositivo de e / s, presentan problemas especiales y distintas soluciones: ∗ Ejecución en modo núcleo, con acceso total al hardware y comunicación con los demás procesos mediante el mecanismo normal de mensajes. ∗ Construcción de un mínimo de mecanismos dentro del núcleo manteniendo las decisiones de política relativas a los usuarios dentro del espacio del usuario. 1.5 Tendencias Las principales tendencias en S. O. son las siguientes [4, Deitel]: • Soporte generalizado para multiprocesamiento. • Migración hacia el microcódigo de funciones de los S. O. realizadas por software. • Distribución del control entre procesadores localizados. • Mejora de la eficiencia en el soporte de la ejecución concurrente de programas. 7 Ver Figura 1.6 de la página 13 [10, Tanenbaum]. 1.5. TENDENCIAS PROCESO CLIENTE 13 PROCESO SERVIDOR SERVIDOR CLIENTE DEL PROC. DE LA TERM . . . SERVIDOR SERVIDOR DE ARCHIV. DE MEMOR. MODO USUARIO MODO NUCLEO NUCLE O LOS CLIENTES OBTIENEN EL SERVICIO AL ENVIAR MENSAJES A LOS PROC. SERVIDORES Figura 1.5: El modelo cliente - servidor. MAQUINA 1 ... MAQUINA 2 MAQUINA 3 MAQUINA 4 CLIENTE SERV. DE ARCHIVOS SER. DE PROCESOS SERV. DE TERMINALES NUCLEO NUCLEO NUCLEO NUCLEO RED MENSAJE DEL CLIENTE AL SERVIDOR Figura 1.6: El modelo cliente - servidor en un sistema distribuido. ... 14 CAPÍTULO 1. INTRODUCCIÓN • Soporte del paralelismo masivo con altísimo grado de concurrencia. • Profundización de los esquemas de máquinas virtuales. • Continuación del esquema de familias de S. O. para familias de computadoras, viendo las aplicaciones máquinas virtuales. • Compatibilidad con nuevas generaciones de computadoras. • Desarrollos en la ingeniería de software para brindar S. O. más preservables, confiables y comprensibles. • Proliferación de redes de sistemas, distribuyendo tareas en equipos sobre los que el usuario puede no tener conocimiento ni control con énfasis en la importancia de la perspectiva de las máquinas virtuales. • Permanencia del concepto de almacenamiento virtual. • Permanencia de la perspectiva del S. O. como administrador de recursos, teniendo presente que los datos serán considerados cada vez más como un recurso para ser administrado. • Profundización del desarrollo de S. O. con funciones distribuidas entre varios procesadores a través de grandes redes de sistemas [12, Tanenbaum]. 1.6 Definiciones Sobre Procesos El concepto central de cualquier Sistema Operativo es el de proceso: una abstracción de un programa en ejecución también llamada tarea. No hay un acuerdo universal sobre una definición de proceso, pero sí algunas definiciones aceptadas [4, Deitel]: • Un programa que se está ejecutando. • Una actividad asincrónica. • El emplazamiento del control de un procedimiento que está siendo ejecutado. • Aquello que se manifiesta por la existencia en el Sistema Operativo de un bloque de control de proceso. • Aquella entidad a la cual son asignados los procesadores. • La unidad despachable. En sistemas de multiprogramación la cpu alterna de programa en programa, en un esquema de seudoparalelismo , es decir que la cpu ejecuta en cierto instante un solo programa, intercambiando muy rápidamente entre uno y otro. El paralelismo real de hardware se da en las siguientes situaciones: 1.6. DEFINICIONES SOBRE PROCESOS 15 • En ejecución de instrucciones de programa con más de un procesador de instrucciones en uso simultáneamente. • Con la superposición de ejecución de instrucciones de programa con la ejecución de una o más operaciones de entrada / salida. El objetivo es aumentar el paralelismo en la ejecución. El modelo de procesos posee las siguientes características: • Todo el software ejecutable, inclusive el Sistema Operativo, se organiza en varios procesos secuenciales o procesos. • Un proceso incluye al programa en ejecución y a los valores activos del contador, registros y variables del mismo. • Conceptualmente cada proceso tiene su propia cpu virtual. • Si la cpu alterna entre los procesos, la velocidad a la que ejecuta un proceso no será uniforme, por lo que es necesario aclarar lo siguiente: — Que los procesos no deben programarse con hipótesis implícitas acerca del tiempo. — Que normalmente la mayoría de los procesos no son afectados por la multiprogramación subyacente de la cpu o las velocidades relativas de procesos distintos. • Un proceso es una actividad de un cierto tipo, que tiene un programa, entrada, salida y estado. • Un solo procesador puede ser compartido entre varios procesos con cierto “algoritmo de planificación” , el cual determina cuándo detener el trabajo en un proceso y dar servicio a otro distinto8 . En cuanto a las jerarquías de procesos es necesario señalar que los Sistemas Operativos deben disponer de una forma de crear y destruir procesos cuando se requiera durante la operación, teniendo además presente que los procesos pueden generar procesos hijos mediante llamadas al Sistema Operativo, pudiendo darse ejecución en paralelo. Respecto de los estados del proceso deben efectuarse las siguientes consideraciones: • Cada proceso es una entidad independiente pero frecuentemente debe interactuar con otros procesos9 . • Los procesos pueden bloquearse en su ejecución porque: — Desde el punto de vista lógico no puede continuar porque espera datos que aún no están disponibles. — El Sistema Operativo asignó la cpu a otro proceso. 8 9 Ver Figura 1.7 de la página 16 [10, Tanenbaum]. Ver Figura 1.8 de la página 16 [10, Tanenbaum]. 16 CAPÍTULO 1. INTRODUCCIÓN UN CONTADOR DE PROGRAMA ALTERNADOR DE PROCESOS A B C MODELO CONCEPTUAL DE CUATRO PROCESOS SECUENCIALES INDEPENDIENTES CUATRO CONTADORES DE PROGRAMA D A C D B Figura 1.7: Multiprogramación de cuatro programas. P R D O C C E S B O A TIEMPO Figura 1.8: Solo un programa está activo en un momento dado. • Los estados [10, Tanenbaum] que puede tener un proceso son10 : — En ejecución: utiliza la cpu en el instante dado. — Listo: ejecutable, se detiene en forma temporal para que se ejecute otro proceso. — Bloqueado: no se puede ejecutar debido a la ocurrencia de algún evento externo. • Son posibles cuatro transiciones entre estos estados. 10 Ver Figura 1.9 de la página 17 [10, Tanenbaum]. 1.7. ESTADOS DE PROCESOS 17 TANSICIONES ENTRE LOS ESTADOS EN EJECUCION 1 2 1-EL PROCESO SE BLOQUEA EN ESPERA DE DATOS 2-EL PLANIFICADOR ELIGE OTRO PROCESO 3-EL PLANIFICADOR ELIGE ESTE PROCESO 4-LOS DATOS ESTAN DISPONIBLES 3 BLOQUEAD O 4 LISTO 1-BLOQUEO 2-TIEMPO EXCEDIDO 3-DESPACHO 4-DESPERTAR Figura 1.9: Un proceso puede estar en ejecución, bloqueado o listo. 1.7 Estados de Procesos Durante su existencia un proceso pasa por una serie de estados discretos, siendo varias las circunstancias que pueden hacer que el mismo cambie de estado. Debido a ello se puede establecer una “Lista de Listos” para los procesos “listos” y una “Lista de Bloqueados” para los “bloqueados”. La “Lista de Listos” se mantiene en orden prioritario y la “Lista de Bloqueados” está desordenada, ya que los procesos se desbloquean en el orden en que tienen lugar los eventos que están esperando. Al admitirse un trabajo en el sistema se crea un proceso equivalente y es insertado en la última parte de la “Lista de Listos”. La asignación de la cpu al primer proceso de la “Lista de Listos” se denomina “Despacho” , que es ejecutado por una entidad del Sistema Operativo llamada “Despachador” . El “Bloqueo” es la única transición de estado iniciada por el propio proceso del usuario, puesto que las otras transiciones son iniciadas por entidades ajenas al proceso. La manifestación de un proceso en un Sistema Operativo es un “Bloque de Control de Proceso” (PCB) con información que incluye [4, Deitel]: • Estado actual del proceso. • Identificación única del proceso. • Prioridad del proceso. • Apuntadores para localizar la memoria del proceso. • Apuntadores para asignar recursos. • Area para preservar registros. Cuando el Sistema Operativo cambia la atención de la cpu entre los procesos, utiliza las áreas de preservación del PCB para mantener la información que necesita para reiniciar el proceso cuando consiga de nuevo la cpu. 18 CAPÍTULO 1. INTRODUCCIÓN Los sistemas que administran los procesos deben poder crear, destruir, suspender, reanudar, cambiar la prioridad, bloquear, despertar y despachar un proceso. La “creación” de un proceso significa: • Dar nombre al proceso. • Insertar un proceso en la lista del sistema de procesos conocidos. • Determinar la prioridad inicial del proceso. • Crear el bloque de control del proceso. • Asignar los recursos iniciales del proceso. Un proceso puede “crear un nuevo proceso”, en cuyo caso el proceso creador se denomina “proceso padre” y el proceso creado “proceso hijo” y se obtiene una “estructura jerárquica de procesos”. La “destrucción” de un proceso implica: • Borrarlo del sistema. • Devolver sus recursos al sistema. • Purgarlo de todas las listas o tablas del sistema. • Borrar su bloque de control de procesos. Un proceso “suspendido” no puede proseguir hasta que otro proceso lo reanude. Reanudar (reactivar) un proceso implica reiniciarlo en el punto donde fue suspendido. La “destrucción” de un proceso puede o no significar la destrucción de los procesos hijos, según el Sistema Operativo. Generalmente se denomina “Tabla de Procesos” al conjunto de información de control sobre los distintos procesos. 1.8 El Núcleo del Sistema Operativo El “núcleo” del Sistema Operativo controla todas las operaciones que implican procesos y representa solo una pequeña porción del código de todo el Sistema Operativo pero es de amplio uso [4, Deitel]. Generalmente permanece en el almacenamiento primario. El proceso de interrupciones se incluye en el núcleo ya que debe ser rápido (especialmente en sistemas multiusuario), para optimizar el uso de los recursos del sistema y proveer tiempos de respuesta aceptables a los usuarios interactivos. El núcleo inhabilita las interrupciones mientras responde a una interrupción. Las interrupciones son habilitadas de nuevo después de completar el proceso de una interrupción. El núcleo del Sistema Operativo generalmente realiza las siguientes funciones: • Manipulación de interrupciones. 1.9. PLANIFICACIÓN DE PROCESOS 19 • Creación y destrucción de procesos. • Cambio de estados de procesos. • Despacho. • Suspensión y reanudación de procesos. • Sincronización de procesos. • Comunicación entre procesos. • Manipulación de bloques de control de proceso. • Soporte de las actividades de Entrada / Salida. • Soporte de la asignación y desasignación de almacenamiento. • Soporte del sistema de archivos. • Soporte de un mecanismo de llamada / regreso al procedimiento. • Soporte de ciertas funciones contables (estadísticas) del sistema. 1.9 Planificación de Procesos Cuando más de un proceso es ejecutable desde el punto de vista lógico, el Sistema Operativo debe decidir cuál de ellos debe ejecutarse en primer término. El Planificador es la porción del Sistema Operativo que decide y el Algoritmo de Planificación es el utilizado. Los principales “criterios” respecto de un buen algoritmo de planificación [10, Tanenbaum] son la equidad, la eficacia, el tiempo de respuesta, el tiempo de regreso y el rendimiento 11 . Algunas de estas metas son contradictorias, por ejemplo, minimizar el tiempo de respuesta para los usuarios interactivos significaría no ejecutar las tareas batch. Cada proceso es único e impredecible, es decir que pueden requerir intensivamente operaciones de Entrada / Salida o intensivamente cpu; el planificador del Sistema Operativo no tiene la certeza de cuánto tiempo transcurrirá hasta que un proceso se bloquee, ya sea por una operación de Entrada / Salida o por otra razón . Para evitar que un proceso se apropie de la cpu un tiempo excesivo, los equipos poseen un dispositivo que provoca una interrupción en forma periódica, por ejemplo 60 hz, o sea sesenta veces por segundo. En cada interrupción del reloj el Sistema Operativo decide si el proceso que se está ejecutando continúa o si el proceso agotó su tiempo de cpu y debe suspenderse y ceder la cpu a otro proceso. Los principales conceptos relacionados con Planificación del Procesador son los siguiente: 11 Ver Tabla 2.1 de la página 34 [10, Tanenbaum]. 20 CAPÍTULO 1. INTRODUCCIÓN Criterio Equidad Eficacia Tiempo de respuesta Tiempo de regreso Rendimiento Descripción Garantizar que cada proceso obtiene su proporción justa de la cpu Mantener ocupada la cpu el ciento por ciento del tiempo Minimizar el tiempo de respuesta para los usuarios interactivos Minimizar el tiempo que deben esperar los usuarios por lotes (batch) para obtener sus resultados Maximizar el número de tareas procesadas por hora Tabla 1.2: Criterios de un buen algoritmo de planificación. • Planificación apropiativa : es la estrategia de permitir que procesos ejecutables (desde el punto de vista lógico) sean suspendidos temporalmente. • Planificación no apropiativa : es la estrategia de permitir la ejecución de un proceso hasta terminar. • Planificación del procesador : determinar cuándo deben asignarse los procesadores y a qué procesos, lo cual es responsabilidad del Sistema Operativo. 1.10 Niveles de Planificación del Procesador Se consideran tres niveles importantes de planificación, los que se detallan a continuación12 : • Planificación de alto nivel: — También se denomina Planificación de trabajos. — Determina a qué trabajos se les va a permitir competir activamente por los recursos del sistema, lo cual se denomina Planificación de admisión. • Planificación de nivel intermedio: — Determina a qué procesos se les puede permitir competir por la cpu. — Responde a fluctuaciones a corto plazo en la carga del sistema y efectúa “suspensiones” y “activaciones” (“reanudaciones”) de procesos. — Debe ayudar a alcanzar ciertas metas en el rendimiento total del sistema. • Planificación de bajo nivel: — Determina a qué proceso listo se le asigna la cpu cuando esta queda disponible y asigna la cpu al mismo, es decir que “despacha” la cpu al proceso. 12 Ver Figura 1.10 de la página 21 [4, Deitel]. 1.11. OBJETIVOS DE LA PLANIFICACIÓN 21 TRABAJOS ESPERANDO E NT R AD A ENTRADA DE TRABAJOS TRABAJOS ESPERANDO INICIACION INICIACION DE TRABAJOS PLANIFICACION DE ALTO NIVEL TRABAJOS SUSPENDIDOS ESPERANDO ACTIVACION ACTIVAR SUSPENDER PLANIFICACION DE NIVEL INTERMEDIO PROCESOS ACTIVOS DESPACHO PLANIFICACION DE BAJO NIVEL PROCESOS EN EJECUCION TERMINAR TERMINADO Figura 1.10: Niveles de planificación del procesador. — La efectúa el Despachador del Sistema Operativo, el que opera muchas veces por segundo y reside siempre en el almacenamiento primario. Los distintos Sistemas Operativos utilizan varias Políticas de Planificación, que se instrumentan mediante Mecanismos de Planificación . 1.11 Objetivos de la Planificación Los objetivos de la planificación del procesador son los siguientes e involucran a los conceptos detallados seguidamente [4, Deitel]: • Ser justa: — Todos los procesos son tratados de igual manera. — Ningún proceso es postergado indefinidamente. 22 CAPÍTULO 1. INTRODUCCIÓN • Maximizar la capacidad de ejecución: — Maximizar el número de procesos servidos por unidad de tiempo. • Maximizar el número de usuarios interactivos que reciban unos tiempos de respuesta aceptables: — En un máximo de unos segundos. • Ser predecible: — Un trabajo dado debe ejecutarse aproximadamente en la misma cantidad de tiempo independientemente de la carga del sistema. • Minimizar la sobrecarga: — No suele considerarse un objetivo muy importante. • Equilibrar el uso de recursos: — Favorecer a los procesos que utilizarán recursos infrautilizados. • Equilibrar respuesta y utilización: — La mejor manera de garantizar buenos tiempos de respuesta es disponer de los recursos suficientes cuando se necesitan, pero la utilización total de recursos podrá ser pobre. • Evitar la postergación indefinida: — Se utiliza la estrategia del “envejecimiento” . — Mientras un proceso espera por un recurso su prioridad debe aumentar, así la prioridad llegará a ser tan alta que el proceso recibirá el recurso esperado. • Asegurar la prioridad: — Los mecanismos de planificación deben favorecer a los procesos con prioridades más altas. • Dar preferencia a los procesos que mantienen recursos claves: — Un proceso de baja prioridad podría mantener un recurso clave, que puede ser requerido por un proceso de más alta prioridad. — Si el recurso es no apropiativo, el mecanismo de planificación debe otorgar al proceso un tratamiento mejor del que le correspondería normalmente, puesto que es necesario liberar rápidamente el recurso clave. 1.12. CONCEPTOS BÁSICOS DE ALMACENAMIENTO VIRTUAL 23 • Dar mejor tratamiento a los procesos que muestren un “comportamiento deseable”: — Un ejemplo de comportamiento deseable es una tasa baja de paginación. • Degradarse suavemente con cargas pesadas: — Un mecanismo de planificación no debe colapsar con el peso de una exigente carga del sistema. — Se debe evitar una carga excesiva mediante las siguientes acciones: ∗ No permitiendo que se creen nuevos procesos cuando la carga ya es pesada. ∗ Dando servicio a la carga más pesada al proporcionar un nivel moderadamente reducido de servicio a todos los procesos. Muchas de estas metas se encuentran en conflicto entre sí, por lo que la planificación se convierte en un problema complejo. 1.12 Conceptos Básicos de Almacenamiento Virtual La clave del concepto de memoria (almacenamiento) virtual esta en la disociación: • De las direcciones a las que hace referencia un programa. • De las direcciones disponibles en la memoria real (almacenamiento primario). Los principales conceptos son los siguientes: • “Direcciones virtuales”: — Son las referidas por un proceso en ejecución. • “Direcciones reales”: — Son las disponibles dentro del almacenamiento primario. • “Espacio de direcciones virtuales (v)” de un proceso: — Es el número de direcciones virtuales a que puede hacer referencia el proceso. • “Espacio de direcciones reales (r)” de un computador: — Es el número de direcciones reales disponibles en el ordenador. Los procesos hacen referencia a direcciones virtuales pero éstas deben ejecutarse en el almacenamiento real: • Las direcciones virtuales deben ser transformadas dentro de las direcciones reales, mientras el proceso está en ejecución. 24 CAPÍTULO 1. INTRODUCCIÓN ALMACENAM. VIRTUAL ALMACENAM. REAL Figura 1.11: Transformación de ítems del espacio de direcciones virtuales al espacio de direcciones reales. • La traducción de direcciones deberá hacerse rápidamente para no degradar al sistema. Existen varios medios para asociar las direcciones virtuales con las reales.13 Los mecanismos de “traducción dinámica de direcciones” (dat) convierten las direcciones virtuales en reales al ejecutarse el proceso. Las direcciones contiguas dentro del espacio de direcciones virtuales de un proceso no tienen por qué ser contiguas dentro del almacenamiento real, a esto se denomina “contigüidad artificial ”.14 1.13 Organización del Almacenamiento de Niveles Múltiples Se deben proporcionar los medios para retener programas y datos en un gran almacenamiento auxiliar para: • Permitir que el espacio de direcciones virtuales de un usuario sea mayor que el espacio de direcciones reales. • Soportar multiprogramación de forma efectiva en un sistema con muchos usuarios que compartan el almacenamiento real. Se utiliza un esquema de almacenamiento de dos niveles:15 • Primer nivel: “almacenamiento real ”: 13 Ver Figura 1.11 de la página 24 [4, Deitel]. Ver Figura 1.12 de la página 25 [4, Deitel]. 15 Ver Figura 1.13 de la página 26 [4, Deitel]. 14 1.14. SISTEMAS DE ARCHIVOS 25 ALMACENAM. VIRTUAL ALMACENAM. REAL LOCALIZACIONES CONTIGUAS DE ALMACENAMIENTO VIRTUAL MECANISMO DE TRANSFORMACION DE DIRECCIONES Figura 1.12: Contigüidad artificial. — En él se ejecutan los procesos y en él deben estar los datos para que un proceso pueda referirse a ellos. • Segundo nivel: “almacenamiento auxiliar, secundario o adicional ”: — Generalmente consta de discos de gran capacidad que pueden mantener los programas y datos que no caben al mismo tiempo en el más limitado almacenamiento real. Cuando se va a ejecutar un proceso su código y datos se pasan al almacenamiento principal. El almacenamiento real es compartido por varios procesos: • Cada proceso puede tener un espacio de direcciones virtuales mucho mayor que el almacenamiento real. • Solo se mantiene al mismo tiempo una pequeña parte de los programas y datos de cada proceso en el almacenamiento real. 1.14 Sistemas de Archivos Todas las aplicaciones computarizadas necesitan almacenar y recuperar la información [4, Deitel]: 26 CAPÍTULO 1. INTRODUCCIÓN ALMACENAM. PRINCIPAL, PRIMARIO O REAL ALMACENAM. SECUNDARIO, AUXILIAR O ADICIONAL DISCOS PROCESADORES ALMACENAM . REAL OTROS DISPOSIT. ALMACENAMIENTO AUXILIAR EL ALMACENAMIENTO VIRTUAL DE UN PROCESO NO NECESITA SER CONTIGUO NI SIQUIERA EN EL ALMACENAMIENTO SECUNDARIO ALMACENAMIENTO REAL ALMACENAMIENTO VIRTUAL DEL PROC. A ALMACENAMIENTO VIRTUAL DEL PROC. B ALMACENAMIENTO VIRTUAL DEL PROC. Z Figura 1.13: Almacenamiento de dos niveles. 1.15. FUNCIONES DEL SISTEMA DE ARCHIVOS 27 • Superando las limitaciones del almacenamiento real. • Trascendiendo a la duración de los procesos que las utilizan o generan. • Independizando a la información de los procesos permitiendo el acceso a la misma a través de varios procesos. Las condiciones esenciales para el almacenamiento de la información a largo plazo son: • Debe ser posible almacenar una cantidad muy grande de información. • La información debe sobrevivir a la conclusión del proceso que la utiliza. • Debe ser posible que varios procesos tengan acceso concurrente a la información. La solución es el almacenamiento de la información en discos y otros medios externos en unidades llamadas archivos: • Los archivos deben ser persistentes, decir que no deben verse afectados por la creación o terminación de un proceso. • Los archivos son una colección de datos con nombre. • Pueden ser manipulados como una unidad por operaciones como: open, close, create, destroy, copy, rename, list. • Los elementos de datos individuales dentro del archivo pueden ser manipulados por operaciones como: read, write, update, insert, delete. El “Sistema de Archivos” es la parte del sistema de administración del almacenamiento responsable, principalmente, de la administración de los archivos del almacenamiento secundario. Es la parte del S. O. responsable de permitir “compartir controladamente” la información de los archivos. 1.15 Funciones del Sistema de Archivos Los usuarios deben poder crear, modificar y borrar archivos. Se deben poder compartir los archivos de una manera cuidadosamente controlada [4, Deitel]. El mecanismo encargado de compartir los archivos debe proporcionar varios tipos de acceso controlado: • Ej.: “Acceso de Lectura”, “Acceso de Escritura”, “Acceso de Ejecución”, varias combinaciones de estos, etc. Se debe poder estructurar los archivos de la manera más apropiada a cada aplicación. Los usuarios deben poder ordenar la transferencia de información entre archivos. Se deben proporcionar posibilidades de “respaldo” y “recuperación” para prevenirse contra: 28 CAPÍTULO 1. INTRODUCCIÓN • La pérdida accidental de información. • La destrucción maliciosa de información. Se debe poder referenciar a los archivos mediante “Nombres Simbólicos”, brindando “Independencia de Dispositivos”. En ambientes sensibles, el sistema de archivos debe proporcionar posibilidades de “Cifrado” y “Descifrado”. El sistema de archivos debe brindar una interfase favorable al usuario: • Debe suministrar una “visión lógica” de los datos y de las funciones que serán ejecutadas, en vez de una “visión física”. • El usuario no debe tener que preocuparse por: — Los dispositivos particulares. — Dónde serán almacenados los datos. — El formato de los datos en los dispositivos. — Los medios físicos de la transferencia de datos hacia y desde los dispositivos. 1.16 El Sistema de Archivos Un “Archivo” es un conjunto de registros relacionados [10, Tanenbaum]. El “Sistema de Archivos” es un componente importante de un S. O. y suele contener [4, Deitel]: • “Métodos de acceso” relacionados con la manera de acceder a los datos almacenados en archivos. • “Administración de archivos” referida a la provisión de mecanismos para que los archivos sean almacenados, referenciados, compartidos y asegurados. • “Administración del almacenamiento auxiliar ” para la asignación de espacio a los archivos en los dispositivos de almacenamiento secundario. • “Integridad del archivo” para garantizar la integridad de la información del archivo. El sistema de archivos está relacionado especialmente con la administración del espacio de almacenamiento secundario, fundamentalmente con el almacenamiento de disco. Una forma de organización de un sistema de archivos puede ser la siguiente: • Se utiliza una “raíz ” para indicar en qué parte del disco comienza el “directorio raíz ”. • El “directorio raíz ” apunta a los “directorios de usuarios”. • Un “directorio de usuario” contiene una entrada para cada uno de los archivos del usuario. 1.17. ENTRADA / SALIDA 29 • Cada entrada de archivo apunta al lugar del disco donde está almacenado el archivo referenciado. Los nombres de archivos solo necesitan ser únicos dentro de un directorio de usuario dado. El nombre del sistema para un archivo dado debe ser único para el sistema de archivos. En sistemas de archivo “jerárquicos” el nombre del sistema para un archivo suele estar formado como el “nombre de la trayectoria” del directorio raíz al archivo. 1.17 Entrada / Salida Una de las funciones principales de un S. O. es el control de todos los dispositivos de e / s de la computadora [10, Tanenbaum]. Las principales funciones relacionadas son: • Enviar comandos a los dispositivos. • Detectar las interrupciones. • Controlar los errores. • Proporcionar una interfaz entre los dispositivos y el resto del sistema: — Debe ser sencilla y fácil de usar. — Debe ser la misma (preferentemente) para todos los dispositivos (independencia del dispositivo). El código de e / s representa una fracción significativa del S. O. El uso inapropiado de los dispositivos de e / s frecuentemente genera ineficiencias del sistema, lo que afecta la performance global. 1.18 Algoritmos de Programación del Brazo del Disco En la mayoría de los discos, el tiempo de búsqueda supera al de retraso rotacional y al de transferencia [10, Tanenbaum], debido a ello, la reducción del tiempo promedio de búsqueda puede mejorar en gran medida el rendimiento del sistema. Si el manejador del disco utiliza el algoritmo primero en llegar primero en ser atendido (FCFS), poco se puede hacer para mejorar el tiempo de búsqueda. Es posible que mientras el brazo realiza una búsqueda para una solicitud, otros procesos generen otras solicitudes. Muchos manejadores tienen una tabla: • El índice es el número de cilindro. • Incluye las solicitudes pendientes para cada cilindro enlazadas entre sí en una lista ligada. 30 CAPÍTULO 1. INTRODUCCIÓN • Cuando concluye una búsqueda, el manejador del disco tiene la opción de elegir la siguiente solicitud a dar paso: — Se atiende primero la solicitud más cercana, para minimizar el tiempo de búsqueda. — Este algoritmo se denomina primero la búsqueda más corta (SSF: shortest seek first). — Reduce a la mitad el número de movimientos del brazo en comparación con FCFS. Ej. de SSF : • Consideramos un disco de 40 cilindros. • Se presenta una solicitud de lectura de un bloque en el cilindro 11. • Durante la búsqueda, llegan solicitudes para los cilindros 1, 36, 16, 34, 9 y 12, en ese orden. • La secuencia de búsqueda SSF será: 12, 9, 16, 1, 34, 36. • Habrá un número de movimientos del brazo para un total de: — 111 cilindros según FCFS. — 61 cilindros según SSF. El algoritmo SSF tiene el siguiente problema: • El ingreso de nuevas solicitudes puede demorar la atención de las más antiguas. • Con un disco muy cargado, el brazo tenderá a permanecer a la mitad del disco la mayoría del tiempo, como consecuencia de ello las solicitudes lejanas a la mitad del disco tendrán un mal servicio. • Entran en conflicto los objetivos de: — Tiempo mínimo de respuesta. — Justicia en la atención. La solución a este problema la brinda el algoritmo del elevador (por su analogía con el ascensor o elevador): • Se mantiene el movimiento del brazo en la misma dirección, hasta que no tiene más solicitudes pendientes en esa dirección; entonces cambia de dirección. • El software debe conservar el bit de dirección actual. Ej. del algoritmo del elevador para el caso anterior, con el valor inicial arriba del bit de dirección: 1.18. ALGORITMOS DE PROGRAMACIÓN DEL BRAZO DEL DISCO 31 • El orden de servicio a los cilindros es: 12, 16, 34, 36, 9 y 1. • El número de movimientos del brazo corresponde a 60 cilindros. El algoritmo del elevador: • Ocasionalmente es mejor que el algoritmo SSF. • Generalmente es peor que SSF. • Dada cualquier colección de solicitudes, la cuota máxima del total de movimientos está fija, siendo el doble del número de cilindros. Una variante consiste en rastrear siempre en la misma dirección: • Luego de servir al cilindro con el número mayor: — El brazo pasa al cilindro de número menor con una solicitud pendiente. — Continúa su movimiento hacia arriba. Algunos controladores de disco permiten que el software inspeccione el número del sector activo debajo del cabezal: • Si dos o más solicitudes para el mismo cilindro están pendientes: — El manejador puede enviar una solicitud para el sector que pasará debajo del cabezal. — Se pueden hacer solicitudes consecutivas de distintas pistas de un mismo cilindro, sin generar un movimiento del brazo. Cuando existen varias unidades, se debe tener una tabla de solicitudes pendientes para cada unidad. Si una unidad está inactiva, deberá buscarse el cilindro siguiente necesario, si el controlador permite búsquedas traslapadas. Cuando termina la transferencia actual se verifica si las unidades están en la posición del cilindro correcto: • Si una o más unidades lo están, se puede iniciar la siguiente transferencia en una unidad ya posicionada. • Si ninguno de los brazos está posicionado, el manejador: — Debe realizar una nueva búsqueda en la unidad que terminó la transferencia. — Debe esperar hasta la siguiente interrupción para ver cuál brazo se posiciona primero. Generalmente, las mejoras tecnológicas de los discos: • Acortan los tiempos de búsqueda (seek). 32 CAPÍTULO 1. INTRODUCCIÓN • No acortan los tiempos de demora rotacional (search). • En algunos discos, el tiempo promedio de búsqueda ya es menor que el retraso rotacional. • El factor dominante será el retraso rotacional, por lo tanto, los algoritmos que optimizan los tiempos de búsqueda (como el algoritmo del elevador) perderán importancia frente a los algoritmos que optimicen el retraso rotacional. Una tecnología importante es la que permite el trabajo conjunto de varios discos. Una configuración interesante es la de treinta y ocho (38) unidades ejecutándose en paralelo. Cuando se realiza una operación de lectura: • Ingresan a la cpu 38 bit a la vez, uno por cada unidad. • Los 38 bits conforman una palabra de 32 bits junto con 6 bits para verificación. • Los bits 1, 2, 4, 8, 16 y 32 se utilizan como bits de paridad. • La palabra de 38 bits se puede codificar mediante el código Hamming, que es un código corrector de errores. • Si una unidad sale de servicio: — Se pierde un bit de cada palabra. — El sistema puede continuar trabajando; se debe a que los códigos Hamming se pueden recuperar de un bit perdido. Este diseño se conoce como RAID; siglas en inglés de “arreglo redundante de discos no costosos”. Capítulo 2 Fundamentos Teóricos 2.1 2.1.1 Procesos y Administración del Procesador Criterios de Planificación Para realizar los objetivos de la planificación, un mecanismo de planificación debe considerar lo siguiente [4, Deitel] • La limitación de un proceso a las operaciones de Entrada / Salida: cuando un proceso consigue la cpu, ¿la utiliza solo brevemente antes de generar una petición de Entrada / Salida?. • La limitación de un proceso a la cpu: cuando un proceso obtiene la cpu, ¿tiende a usarla hasta que expira su tiempo?. • Si un proceso es por lote (batch) o interactivo: los usuarios interactivos deben recibir inmediato servicio para garantizar buenos tiempos de respuesta. • ¿Qué urgencia tiene una respuesta rápida?: por ejemplo, un proceso de tiempo real de un sistema de control que supervise una re.nería de combustible requiere una respuesta rápida, más rápida que la respuesta requerida por un proceso en lotes (batch) que deberá entregarse al día siguiente. • La prioridad de un proceso: a mayor prioridad mejor tratamiento. • Frecuentemente un proceso genera fallos (carencias) de página: — Probablemente los procesos que generan pocos fallos de página hayan acumulado sus .conjuntos de trabajo. en el almacenamiento principal. — Los procesos que experimentan gran cantidad de fallos de página aún no han establecido sus conjuntos de trabajo. — Un criterio indica favorecer a los procesos que han establecido sus conjuntos de trabajo. — Otro criterio indica favorecer a los procesos con una tasa alta de fallos de página ya que rápidamente generarán una petición de Entrada / Salida. 33 34 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Disciplina Apropiativa No Apropiativa Descripción Una vez que se le ha otorgado la cpu a un proceso, le puede ser retirada Una vez que se le ha otorgado la cpu a un proceso, no le puede ser retirada Tabla 2.1: Criterios de un buen algoritmo de planificación. • Frecuentemente un proceso ha sido apropiado por otro de más alta prioridad, lo cual significa lo siguiente: — A menudo los procesos apropiados deben recibir un tratamiento menos favorable. — Cada vez que el Sistema Operativo asume la sobrecarga para hacer ejecutar este proceso, el corto tiempo de ejecución antes de la apropiación no justifica la sobrecarga de hacer ejecutar al proceso en primer lugar. • ¿Cuánto tiempo de ejecución real ha recibido el proceso?: un criterio considera que • debe ser favorecido un proceso que ha recibido muy poco tiempo de cpu. • ¿Cuánto tiempo adicional va a necesitar el proceso para terminar?: los tiempos promedio de espera pueden reducirse priorizando los procesos que requieren de un tiempo de ejecución mínimo para su terminación, pero pocas veces es posible conocer la cantidad de tiempo adicional que cada proceso necesita para terminar. 2.2 Planificación Apropiativa Versus No Apropiativa Las Disciplinas de Planificación pueden ser Apropiativas o No Apropiativas1 . Las principales características de la planificación apropiativa son las siguientes: • Es útil cuando los procesos de alta prioridad requieren atención rápida. • Es importante para garantizar buenos tiempos de respuesta en sistemas interactivos de tiempo compartido. • Tiene su costo en recursos, ya que el intercambio de contexto implica sobrecarga y además requiere mantener muchos procesos en el almacenamiento principal, en espera de la cpu, lo que también implica sobrecarga. Las principales características de la planfiicación no apropiativa son las siguientes: • Significa que los trabajos largos hacen esperar a los trabajoscortos. • Logra más equidad en el tratamiento de los procesos. 1 Ver Figura ?? de la página ?? [10, Tanenbaum]. 2.3. TEMPORIZADOR DE INTERVALOS O RELOJ DE INTERRUPCIÓN 35 • Logra hacer más predecibles los tiempos de respuesta puesto que los trabajos nuevos de prioridad alta no pueden desplazar a los trabajos en espera. El diseño de un mecanismo apropiativo hace necesario considerar las arbitrariedades de casi cualquier esquema de prioridades, en razón de que muchas veces las propias prioridades no son asignadas de forma significativa [11, Tanenbaum]. El mecanismo debería ser sencillo pero efectivo y significativo.. 2.3 Temporizador de Intervalos o Reloj de Interrupción El proceso al cual está asignada la cpu se dice que está en ejecución y puede ser un proceso de Sistema Operativo o de usuario. El Sistema Operativo dispone de mecanismos para quitarle la cpu a un proceso de usuario para evitar que monopolice el sistema. El Sistema Operativo posee un reloj de interrupción o temporizador de intervalos para generar una interrupción, en algún tiempo futuro especí.co o después de un transcurso de tiempo en el futuro; la cpu es entonces despachada hacia el siguiente proceso [4, Deitel]. Un proceso retiene el control de la cpu hasta que ocurra alguna de las siguientes situaciones: • La libera voluntariamente. • El reloj la interrumpe. • Alguna otra interrupción atrae la atención de la cpu. Si el reloj interrumpe un proceso de usuario, la interrupción causa la ejecución del Sistema Operativo, el que decide cuál será el proceso que obtendrá la cpu. El reloj de interrupción ayuda a garantizar tiempos de respuesta razonables a usuarios interactivos, ya que evita que el sistema se .cuelgue. a un solo usuario en un ciclo in.nito y permite que los procesos respondan a eventos dependientes del tiempo. Asimismo, los procesos que necesitan una ejecución periódica dependen del reloj de interrupción [9, Tanenbaum]. 2.4 Prioridades Las prioridades pueden ser de distinto tipo2 . En el caso de prioridades asignadas arbitrariamente, un mecanismo del sistema necesita distinguir entre procesos sin importarle cuál es el más importante. Las principales características de las prioridades estáticas son las siguientes: • No cambian. • Los mecanismos de implementación son sencillos. 2 Ver Figura 2.2 de la página 36 [4, Deitel]. 36 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Tipos de prioridades Asignadas automáticamente por el sistema Asignadas desde el exterior Dinámicas Estáticas Asignadas racionalmente Asignadas arbitrariamente Tabla 2.2: Tipos de prioridades • Implican una sobrecarga relativamente baja. • No responden a cambios en el ambiente (contexto) que harían deseable ajustar alguna prioridad. Las principales características de las prioridades dinámicas son las siguientes: • Responden al cambio. • La prioridad inicial asignada a un proceso puede durar poco tiempo, luego se la reajusta a un mejor valor. • Los mecanismos de implementación son más complicados que para prioridades estáticas. • Implican una sobrecarga mayor que para esquemas estáticos. Respecto de las prioridades adquiridas, se hace referencia al tratamiento especial que en situaciones excepcionales requiere un cierto proceso, lo que puede signi.car restar recursos a los demás procesos. 2.5 Tipos de Planificación 2.5.1 Planificación a Plazo Fijo Ciertos trabajos se planifican para ser terminados en un tiempo específico o plazo fijo. Es una planificación compleja debido a los siguientes factores: • El usuario debe suministrar anticipadamente una lista precisa de recursos necesarios para el proceso, pero generalmente no se dispone de dicha información. • La ejecución del trabajo de plazo fijo no debe producir una grave degradación del servicio a otros usuarios. • El sistema debe planificar cuidadosamente sus necesidades de recursos hasta el plazo fijo, lo que se puede complicar con las demandas de recursos de nuevos procesos que ingresen al sistema. 2.5. TIPOS DE PLANIFICACIÓN 37 • La concurrencia de varios procesos de plazo fijo (activos a la vez) puede requerir métodos sofisticados de optimización. • La administración intensiva de recursos puede generar una considerable sobrecarga adicional. 2.5.2 Planificación Garantizada Se establecen compromisos de desempeño con el proceso del usuario, por ejemplo, si existen n procesos en el sistema, el proceso del usuario recibirá cerca del 1/n de la potencia de la cpu. El sistema debe tener un registro del tiempo de cpu que cada proceso ha tenido desde su entrada al sistema y del tiempo transcurrido desde esa entrada. Con los datos anteriores y el registro de procesos en curso de ejecución, el sistema calcula y determina qué procesos están más alejados por defecto de la relación 1/n prometida y prioriza los procesos que han recibido menos cpu de la prometida. 2.5.3 Planificación del Primero en Entrar Primero en Salir (FIFO) Es muy simple, los procesos se despachan de acuerdo con su tiempo de llegada a la cola de listos. Una vez que el proceso obtiene la cpu, se ejecuta hasta terminar, ya que es una disciplina no apropiativa.. Puede ocasionar que procesos largos hagan esperar a procesos cortos y que procesos no importantes hagan esperar a procesos importantes. Es más predecible que otros esquemas. No puede garantizar buenos tiempos de respuesta interactivos. Suele utilizarse integrado a otros esquemas, por ejemplo, de la siguiente manera: • Los procesos se despachan con algún esquema de prioridad. • Los procesos con igual prioridad se despachan FIFO. 2.5.4 Planificación de Asignación en Rueda (RR: Round Robin) Los procesos se despachan en FIFO y disponen de una cantidad limitada de tiempo de cpu, llamada división de tiempo o cuanto. Si un proceso no termina antes de expirar su tiempo de cpu ocurren las siguientes acciones: 1. La cpu es apropiada. 2. La cpu es otorgada al siguiente proceso en espera. 3. El proceso apropiado es situado al .nal de la lista de listos. Es efectiva en ambientes de tiempo compartido. La sobrecarga de la apropiación se mantiene baja mediante mecanismos eficientes de intercambio de contexto y con suficiente memoria principal para los procesos. 38 2.5.5 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Tamaño del Cuanto o Quantum La determinación del tamaño del cuanto es decisiva para la operación efectiva de un sistema computacional [4, Deitel]. Los interrogantes son: ¿cuanto pequeño o grande?, ¿cuanto .jo o variable? y ¿cuanto igual para todos los procesos de usuarios o determinado por separado para cada uno de ellos?. Si el cuanto se hace muy grande, cada proceso recibe todo el tiempo necesario para llegar a su terminación, por lo cual la asignación en rueda (RR) degenera en FIFO. Si el cuanto se hace muy pequeño, la sobrecarga del intercambio de contexto se convierte en un factor dominante y el rendimiento del sistema se degrada, puesto que la mayor parte del tiempo de cpu se invierte en el intercambio del procesador (cambio de contexto) y los procesos de usuario disponen de muy poco tiempo de cpu. El cuanto debe ser lo su.cientemente grande como para permitir que la gran mayoría de las peticiones interactivas requieran de menos tiempo que la duración del cuanto, es decir que el tiempo transcurrido desde el otorgamiento de la cpu a un proceso hasta que genera una petición de Entrada / Salida debe ser menor que el cuanto establecido, de esta forma, ocurrida la petición la cpu pasa a otro proceso y como el cuanto es mayor que el tiempo transcurrido hasta la petición de Entrada / Salida, los procesos trabajan al máximo de velocidad, se minimiza la sobrecarga de apropiación y se maximiza la utilización de la Entrada / Salida. El cuanto óptimo varía de un sistema a otro y con la carga, siendo un valor de referencia 100 mseg (cien milisegundos). 2.5.6 Planificación del Trabajo Más Corto Primero (SJF) Es una disciplina no apropiativa y por lo tanto no recomendable en ambientes de tiempo compartido. El proceso en espera con el menor tiempo estimado de ejecución hasta su terminación es el siguiente en ejecutarse. Los tiempos promedio de espera son menores que con FIFO. Los tiempos de espera son menos predecibles que en FIFO. Favorece a los procesos cortos en detrimento de los largos. Tiende a reducir el número de procesos en espera y el número de procesos que esperan detrás de procesos largos. Requiere un conocimiento preciso del tiempo de ejecución de un proceso, lo que generalmente se desconoce. Se pueden estimar los tiempos en base a series de valores anteriores. 2.5. TIPOS DE PLANIFICACIÓN 2.5.7 39 Planificación del Tiempo Restante Más Corto (SRT) Es la contraparte apropiativa del SJF. Es útil en sistemas de tiempo compartido. El proceso con el tiempo estimado de ejecución menor para .nalizar es el siguiente en ser ejecutado. Un proceso en ejecución puede ser apropiado por un nuevo proceso con un tiempo estimado de ejecución menor. 2.5.8 Tiene mayor sobrecarga que la planificación SJF. Debe mantener un registro del tiempo de servicio transcurrido del proceso en ejecución, lo que aumenta la sobrecarga. Los trabajos largos tienen un promedio y una varianza de los tiempos de espera aún mayor que en SJF. La apropiación de un proceso a punto de terminar por otro de menor duración recién llegado podría significar un mayor tiempo de cambio de contexto (administración del procesador) que el tiempo de finalización del primero. Al diseñarse los Sistemas Operativos se debe considerar cuidadosamente la sobrecarga de los mecanismos de administración de recursos comparándola con los beneficios esperados. 2.5.9 Planificación el Siguiente con Relación de Respuesta Máxima HRN Corrige algunas de las debilidades del SJF, tales como el exceso de perjuicio hacia los procesos (trabajos) largos y el exceso de favoritismo hacia los nuevos trabajos cortos. Es una disciplina no apropiativa. La prioridad de cada proceso está en función no sólo del tiempo de servicio del trabajo, sino que también in.uye la cantidad de tiempo que el trabajo ha estado esperando ser servido. Cuando un proceso ha obtenido la cpu, corre hasta terminar. Las prioridades, que son dinámicas, se calculan según la siguiente fórmula, donde pr es la prioridad., te es el tiempo de espera. y ts es el tiempo de servicio: pr= 2.5.10 (te + ts) ts Planificación por Prioridad Considera factores externos al proceso [10, Tanenbaum]. Las ideas centrales son que cada proceso tiene asociada una prioridad y que el proceso ejecutable con máxima prioridad es el que tiene el permiso de ejecución. Los procesos de alta prioridad podrían ejecutar indefinidamente, ya que el planificador del sistema puede disminuir la prioridad del proceso en ejecución en cada interrupción del reloj. Las prioridades también pueden ser asignadas dinámicamente por el sistema para lograr ciertas metas relacionadas con el procesador o la Entrada / Salida. 40 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Los procesos limitados por la Entrada / Salida (requerimientos intensivos de Entrada / Salida) ocupan mucho de su tiempo en espera de operaciones de Entrada / Salida, por lo tanto: • Deben tener prioridad para usar la cpu y efectuar la siguiente petición de Entrada / Salida, ya que se ejecutará (la operación de Entrada / Salida) en paralelo con otro proceso que utilice la cpu. • Si deben esperar mucho tiempo a la cpu estarán ocupando memoria por un tiempo innecesario. Un algoritmo sencillo consiste en establecer que la prioridad sea 1/f, donde f es la fracción del último cuanto utilizado por el proceso. Un proceso que utilice 2 mseg (dos milisegundos) de su cuanto de 100 mseg (cien milisegundos) tendrá prioridad 50 (cincuenta). Un proceso que se ejecutó 50 mseg antes del bloqueo tendrá prioridad 2. Un proceso que utilizó todo el cuanto tendrá prioridad 1. Frecuentemente los procesos se agrupan en Clases de Prioridad, en cuyo caso se utiliza la Planificación con Prioridades entre las clases y con Round Robin (RR) dentro de cada clase. Si las prioridades no se reajustan en algún momento, los procesos de las clases de prioridad mínima podrían demorarse indefinidamente. 2.5.11 Colas de Retroalimentación de Niveles Múltiples Proporcionan una estructura para lograr los siguientes objetivos: Favorecer trabajos cortos. Favorecer trabajos limitados por la Entrada / Salida para optimizar el uso de los dispositivos de Entrada / Salida. Determinar la naturaleza de un trabajo lo más rápido posible y planificar el trabajo (proceso) en consecuencia. Un nuevo proceso entra en la red de línea de espera al .nal de la cola superior. Se mueve por esta cola .FIFO. hasta obtener la cpu. Si el trabajo termina o abandona la cpu para esperar por la terminación de una operación de Entrada / Salida o la terminación de algún otro suceso, el trabajo abandona la red de línea de espera. Si su cuanto expira antes de abandonar la cpu voluntariamente, el proceso se coloca en la parte trasera de la cola del siguiente nivel inferior. El trabajo recibe servicio al llegar a la cabeza de esta cola si la primera está vacía. Mientras el proceso continúe consumiendo totalmente su cuanto en cada nivel, continuará moviéndose hacia el .nal de las colas inferiores. Generalmente hay una cola en la parte más profunda a través de la cual el proceso circula en asignación de rueda hasta que termina. Existen esquemas en los que el cuanto otorgado al proceso aumenta a medida que el proceso se mueve hacia las colas de los niveles inferiores, en tal caso, cuanto más tiempo haya estado el proceso en la red de línea de espera, mayor será su cuanto cada vez que obtiene la cpu y no podrá obtener la cpu muy a menudo debido a la mayor prioridad de los procesos de las colas superiores. 2.5. TIPOS DE PLANIFICACIÓN 41 Un proceso situado en una cola dada no podrá ser ejecutado hasta que las colas de los niveles superiores estén vacías. Un proceso en ejecución es apropiado por un proceso que llegue a una cola superior. Es un mecanismo adaptable, es decir que se adapta a cargas variables. A los efectos de una revisión gráfica de lo enunciado precedentemente, ver la figura 2.1 de la pág.42, [4, Deitel]. 2.5.12 Política Versus Mecanismo de Planificación Puede ocurrir que haya procesos con muchos procesos hijos ejecutándose bajo su control, por ejemplo, un proceso en un DBMS con procesos hijos atendiendo funciones especí.cas, tales como, análisis de interrogantes, acceso a discos, etc. Es posible que el proceso principal (padre) pueda identificar la importancia (o criticidad) de sus procesos hijos, pero los planificadores analizados no aceptan datos de los procesos de usuario relativos a decisiones de planificación. La solución es separar el mecanismo de planificación de la política de planificación , para ello se parametriza el algoritmo de planificación y los parámetros pueden ser determinados por medio de procesos del usuario; así el mecanismo está en el núcleo del Sistema Operativo pero la política queda establecida por un proceso del usuario. 2.5.13 Planificación de Dos Niveles Los esquemas analizados hasta ahora suponen que todos los procesos ejecutables están en la memoria principal. Si la memoria principal es insuficiente, ocurrirá lo siguiente [10, Tanenbaum]: • Habrá procesos ejecutables que se mantengan en disco. • Habrá importantes implicaciones para la planificación, tales como las siguientes: — El tiempo de alternancia entre procesos para traer y procesar un proceso del disco es considerablemente mayor que el tiempo para un proceso que ya está en la memoria principal. — Es más eficiente el intercambio de los procesos con un plani.cador de dos niveles. El esquema operativo de un plani.cador de dos niveles es como sigue: Se carga en la memoria principal cierto subconjunto de los procesos ejecutables. 1. El planificador se restringe a ellos durante cierto tiempo. 2. Periódicamente se llama a un plani.cador de nivel superior para efectuar las siguientes tareas: • Eliminar de la memoria los procesos que hayan permanecido en ella el tiempo suficiente. • Cargar a memoria los procesos que hayan estado en disco demasiado tiempo. 42 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Figura 2.1: Tipos de planificación del procesador 2.6. ESTRATEGIAS DE ADMINISTRACIÓN DEL ALMACENAMIENTO VIRTUAL43 3. El planificador de nivel inferior se restringe de nuevo a los procesos ejecutables que se encuentren en la memoria. 4. El planificador de nivel superior se encarga de desplazar los procesos de memoria a disco y viceversa. Los criterios que podría utilizar el planificador de nivel superior para tomar sus decisiones son los que se indican a continuación: • ¿Cuánto tiempo ha transcurrido desde el último intercambio del proceso?. • ¿Cuánto tiempo de cpu ha utilizado recientemente el proceso?. • ¿Qué tan grande es el proceso? (generalmente los procesos pequeños no causan tantos problemas en este sentido). • ¿Qué tan alta es la prioridad del proceso?. El planificador de nivel superior podría utilizar cualquiera de los métodos de planificación analizados. 2.6 Estrategias de Administración del Almacenamiento Virtual Las diferentes organizaciones de almacenamiento virtual generalmente implementadas son [4, Deitel]: • Paginación. • Segmentación. • Segmentación y paginación. Las estrategias para la administración de sistemas de almacenamiento virtual condicionan la conducta de los sistemas de almacenamiento virtual que operan según esas estrategias. Se consideran las siguientes estrategias: Estrategias de búsqueda.: — Tratan de los casos en que una página o segmento deben ser traídos del almacenamiento secundario al primario. — Las estrategias de búsqueda por demanda esperan a que se haga referencia a una página o segmento por un proceso antes de traerlos al almacenamiento primario. — Los esquemas de búsqueda anticipada intentan determinar por adelantado a qué páginas o segmentos hará referencia un proceso para traerlos al almacenamiento primario antes de ser explícitamente referenciados. 44 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Estrategias de colocación: — Tratan del lugar del almacenamiento primario donde se colocará una nueva página o segmento. — Los sistemas toman las decisiones de colocación de una forma trivial ya que una nueva página puede ser colocada dentro de cualquier marco de página disponible. Estrategias de reposición: — Tratan de la decisión de cuál página o segmento desplazar para hacer sitio a una nueva página o segmento cuando el almacenamiento primario está completamente comprometido. 2.6.1 Estrategias de Reposición de Página Las principales son: • El principio de optimización. • Reposición de páginas al azar. • Primero en entrar - primero en salir. • Menos recientemente usada. • Menos frecuentemente usada. • No usada recientemente. • Conjuntos de trabajo. 2.6.2 El Principio de Optimización El principio de optimización indica que para obtener un rendimiento óptimo, la página que se va a reponer es una que no se va a utilizar en el futuro durante el período de tiempo más largo. El problema es que no es factible predecir el futuro. 2.6.3 Reposición de Página al Azar Consiste en escoger al azar la página que va a ser reemplazada. Todas las páginas del almacenamiento principal deben tener la misma probabilidad de ser reemplazadas. Debe poder seleccionar cualquier página, incluyendo la que va a ser referenciada a continuación (peor selección). Este esquema es raramente usado. 2.6. ESTRATEGIAS DE ADMINISTRACIÓN DEL ALMACENAMIENTO VIRTUAL45 Figura 2.2: Ejemplo de anomalía de FIFO. 2.6.4 Reposición de Página por el Sistema de Primero en Entrar - Primero en Salir (FIFO) Se registra el momento en que cada página ingresa al almacenamiento primario. Para reemplazar una página, se selecciona aquella que ha estado más tiempo almacenada. Se presenta el inconveniente de que se pueden reemplazar páginas muy usadas, que serán llamadas de nuevo al almacenamiento primario casi de inmediato. Se puede presentar la llamada anomalía FIFO: • Belady, Nelson y Shedler descubrieron que con la reposición FIFO, ciertos patrones de referencias de páginas causan más fallos de páginas cuando se aumenta el número de marcos (celdas) de páginas asignados a un proceso: en esto consiste la anomalía FIFO. • Esta anomalía contradice a la intuición 3 . 2.6.5 Reposición de Página Menos - Recientemente - Usada (LRU) Esta estrategia selecciona para ser reemplazada la página que no ha sido usada durante el mayor período de tiempo. 3 Ver Figura 2.2 de la página 45 [4, Deitel]. 46 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Se basa en la heurística de que el pasado reciente es un buen indicador del futuro próximo. Requiere que cada página reciba un sello de tiempo cada vez que se referencia: • Puede significar una sobrecarga adicional importante. • No se implementa frecuentemente. La página seleccionada para reemplazo podría ser la próxima en ser requerida, por lo que habría que paginarla de nuevo al almacenamiento principal casi de inmediato. 2.6.6 Reposición de Página Menos - Frecuentemente - Usada (LFU) Acá interesa la intensidad de uso que haya tenido cada página. La página que será reemplazada es aquella que ha sido usada con menos frecuencia o que ha sido referida con menos intensidad. El inconveniente es que se puede seleccionar fácilmente para su reposición la página equivocada: • Ej.: La página de uso menos frecuente puede ser la página de entrada más reciente al almacenamiento principal, y por lo tanto existe una alta probabilidad de que sea usada de inmediato. 2.6.7 Reposición de Página No Usada - Recientemente (NUR) Presupone que las páginas que no han tenido uso reciente tienen poca probabilidad de ser usadas en el futuro próximo y pueden ser reemplazadas por otras nuevas. Es deseable reemplazar una página que no ha sido cambiada mientras estaba en el almacenamiento primario. La estrategia NUR se implementa con la adición de dos bits de hardware por página: • Bit referenciado: — = 0 si la página no ha sido referenciada. — = 1 si la página ha sido referenciada. • Bit modificado (también llamado bit sucio): — = 0 si la página no ha sido modificada. — = 1 si la página ha sido modificada. La selección de la página que será reemplazada comienza buscando una página que no ha sido referenciada, pero si no la encuentra habrá que reemplazar una página que ha sido referenciada. Si una página ha sido referenciada se comprueba si ha sido modificada o no: • Si no ha sido modificada se la reemplaza: 2.6. ESTRATEGIAS DE ADMINISTRACIÓN DEL ALMACENAMIENTO VIRTUAL47 — Su reposición representa menos sobrecarga que la de una página modi.cada, ya que debería grabarse de nuevo en el almacenamientos secundario. • Si no se encuentra una página que no ha sido modi.cada será reemplazada una página modificada. Con el transcurso del tiempo la mayoría de los bits referenciados serán activados: • Se pierde la capacidad para distinguir las páginas más deseables para ser reemplazadas. Para evitarlo se ajustan periódicamente todos los bits referenciados a 0 : — Se logra un nuevo inicio. — Se vuelve vulnerable al reemplazo aún a las páginas activas, pero solo brevemente,mientras se reajustan los bits. Los bits modificados no se ajustan periódicamente según esta estrategia. 2.6.8 Localidad El concepto de localidad expresa [4, Deitel]: Los procesos tienden a hacer referencia al almacenamiento en patrones no uniformes y muy localizados. La .localidad. se mani.esta en el tiempo y en el espacio: • Es una propiedad empírica (observada). • Nunca está garantizada pero es altamente probable. • Ej.: Los procesos tienden a favorecer ciertos subconjuntos de páginas, las que tienden a ser adyacentes entre sí en el espacio de direcciones virtuales del proceso. • Está relacionada con la forma en que se escriben los programas y se organizan los datos. — Localidad temporal.: signi.ca que las localidades de almacenamiento referenciadas recientemente tienen una alta probabilidad de ser referenciadas en un futuro próximo: • Se apoya en la utilización de: — Formación de ciclos (loops). — Subrutinas. — Pilas. — Variables usadas para contar y totalizar. 48 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Localidad en el espacio.: significa que las referencias de almacenamiento tienden a acumularse de manera tal que, una vez que se hace referencia a una localidad, es muy probable que las localidades cercanas sean también referenciadas: • Se apoya en la utilización de: — Recorrido de arreglos. — Ejecución secuencial de código. — Tendencia de los programadores a colocar de.niciones de variables relacionadas, próximas entre sí. Un programa puede ejecutar eficientemente mientras su subconjunto de páginas preferido se encuentre en el almacenamiento primario. El número de fallos de páginas de un proceso depende de la cantidad de almacenamiento primario disponible para sus páginas. Generalmente los procesos no muestran patrones de referencias aleatorios uniformemente distribuidos por sus diferentes páginas. Al reducir el número de marcos (celdas) de páginas disponibles para un proceso existe un intervalo durante el cual la razón de fallos de páginas no se afecta excesivamente. En determinado punto, cuando se reduce más el número de marcos de páginas, el número de fallos de páginas aumenta drásticamente. Mientras el subconjunto de páginas favorecidas por un proceso permanezca en el almacenamiento primario, el número de fallos de páginas no aumenta mucho. Tan pronto como las páginas del subconjunto favorecido son retiradas del almacenamiento primario, la actividad de paginación del proceso aumenta en gran medida al referenciar y traer de nuevo estas páginas al almacenamiento primario. Los subconjuntos favorecidos también son llamados conjuntos de trabajo o working sets 4. 2.6.9 Conjuntos de Trabajo Denning desarrolló un punto de vista de la actividad de paginación de un programa llamado la teoría de conjunto de trabajo del comportamiento de un programa [4, Deitel] . Un conjunto de trabajo es una colección de páginas a las cuales un proceso hace activamente referencia. Denning sostenía que para que un programa se ejecutara eficientemente, su conjunto de trabajo debe ser mantenido en el almacenamiento primario, para evitar la hiperpaginación. Una política de administración de almacenamiento por conjunto de trabajo trata de mantener el conjunto de trabajo de los programas activos en el almacenamiento primario. La decisión de añadir un nuevo proceso al conjunto activo de procesos (aumentar el nivel de multiprogramación): • Se basa en si hay suficiente espacio disponible en el almacenamiento primario como para acomodar el conjunto de trabajo del nuevo proceso. 4 Ver Figura 2.3 de la página 49 [4, Deitel]. 2.6. ESTRATEGIAS DE ADMINISTRACIÓN DEL ALMACENAMIENTO VIRTUAL49 Figura 2.3: Fenómeno de localidad. • Se toma generalmente de forma heurística ya que es imposible para el sistema conocer por anticipado el tamaño del conjunto de trabajo de un proceso dado. El conjunto de trabajo de páginas de un proceso w (t,w) en el momento t es el conjunto de páginas referidas por un proceso durante el intervalo de tiempo del proceso t - w a t.5 . El tiempo del proceso es el tiempo durante el cual este proceso tiene la cpu. La variable w se denomina tamaño de la ventana del conjunto de trabajo: • La determinación del tamaño de w es muy importante. • Al aumentar el tamaño de la ventana .w. aumenta el tamaño del conjunto de trabajo6 . El verdadero conjunto de trabajo de un proceso es el conjunto de páginas que deben estar en el almacenamiento primario para la ejecución eficaz de este proceso. Los conjuntos de trabajo cambian mientras un proceso está en ejecución: • Complica la administración precisa del almacenamiento primario en base a esta estrategia. • Los conjuntos de trabajo son transitorios y el siguiente conjunto de trabajo del proceso puede diferir substancialmente de su conjunto de trabajo anterior. 5 6 Ver Figura 2.5 de la página 50 [4, Deitel]. Ver Figura 2.4 de la página 50 [4, Deitel]. 50 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Figura 2.4: Una definición del conjunto de trabajo de páginas de un proceso. Figura 2.5: Tamaño del conjunto de trabajo como una función del tamaño de la ventana. 2.7. PAGINACIÓN POR DEMANDA Y PAGINACIÓN ANTICIPADA 2.7 2.7.1 51 Paginación por Demanda y Paginación Anticipada Paginación por Demanda Las paginas son cargadas por demanda [4, Deitel]. No se llevan páginas del almacenamiento secundario al primario hasta que son referenciadas explícitamente por un proceso en ejecución. Las razones del atractivo de esta estrategia son: • Los resultados de computabilidad, en especial el problema de parada, indican que el camino que tomará la ejecución de un programa no se puede predecir con exactitud. • Garantiza que solo las páginas que necesita el proceso sean traídas al almacenamiento principal. • La sobrecarga de proceso para decidir qué página traer al almacenamiento principal es mínima. El principal inconveniente está en los procesos que requieren acumular sus páginas una por una: • Los tiempos de espera de páginas son considerables. • Es creciente la cantidad de almacenamiento primario afectada al proceso que espera páginas, por lo que el producto espacio - tiempo se incrementa. El producto espacio - tiempo indica la cantidad de almacenamiento que usa un proceso y la cantidad de tiempo que lo usa. La reducción del producto espacio - tiempo de las esperas de páginas de un proceso es una meta importante de las estrategias de administración del almacenamiento 7 . 2.7.2 Paginación Anticipada Un proceso usuario puede emitir una .liberación voluntaria de página. para liberar el marco de página cuando ya no necesitara esa página [4, Deitel]. Se puede eliminar el desperdicio y acelerar la ejecución. El inconveniente es que la incorporación de mandatos de liberación de páginas dentro de los programas de usuarios puede ser peligroso y retrasar el desarrollo de aplicaciones. Los compiladores y S. O. deberían detectar automáticamente situaciones de liberación de página mucho antes de lo que es posible con estrategias de conjuntos de trabajo. 2.7.3 Tamaño de Página Generalmente el almacenamiento real se divide en marcos o celdas de página de tamaño fijo [4, Deitel]. Los interrogantes tienen que ver con el tamaño de las páginas, si todas las páginas tendrán igual tamaño, si en caso de utilizar páginas de diferente tamaño las páginas mayores deben ser o no múltiplos enteros de las menores, etc. 7 Ver Figura 2.6 de la página 52 [4, Deitel]. 52 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Figura 2.6: Producto espacio - tiempo con paginación por demanda. Algunas consideraciones para determinar el tamaño de página son las siguientes: Cuanto más pequeño sea el tamaño de una página, más páginas y marcos de páginas habrá y mayores serán las tablas de páginas: — El desperdicio de almacenamiento debido al tamaño excesivo de las tablas de página se llama fragmentación de tablas. — Esto indica la necesidad de páginas más grandes. • Con páginas grandes, grandes cantidades de información que nunca llegaría a ser referenciada, se paginarán hacia el almacenamiento primario: — Esto indica la necesidad de páginas más pequeñas. • Debido a que las transferencias de e / s del disco (paginación) consumen bastante tiempo, se debe minimizar la paginación que un proceso requiera: — Esto indica la necesidad de páginas grandes. • Los programas tienden a mostrar la propiedad de localidad de referencia y esta localidad tiende a ser pequeña: — Esto indica la necesidad de páginas pequeñas. • Los procedimientos y datos rara vez comprenden un número entero de páginas, por lo que los sistemas de paginación experimentan una .fragmentación interna.: — El desperdicio promedio es de 1 / 2 página no usada por segmento (grupo) de páginas, que estará en la última página del segmento. — Esto indica la necesidad de páginas pequeñas. Los tamaños de pagina mas utilizados son: 512 b, 1 kb, 2 kb, 4 kb. 2.8. PORQUÉ ES NECESARIA LA PLANIFICACIÓN DE DISCOS 2.7.4 53 Comportamiento de un Programa en la Paginación Respecto del porcentaje de las páginas de un proceso típico referenciadas desde el momento de iniciarse su ejecución [4, Deitel]: • Un proceso tiende a hacer referencia a una parte significativa de sus páginas inmediatamente después de iniciar su ejecución. • El proceso puede concluir sin haber referenciado a algunas de sus páginas, correspondientes a rutinas que atienden errores que no se produjeron. Respecto de variar el tamaño de la página manteniendo constante la cantidad de almacenamiento primario: • El número de fallos de páginas experimentados por un proceso en ejecución tiende a aumentar con el tamaño de la página, debido a que se traen al almacenamiento primario un mayor número de procedimientos y datos que no serán referenciados, restando lugar para los que sí lo serán. Respecto de cómo el promedio de tiempo interfallos (tiempo entre fallos de página) varía al aumentar el número de marcos de página asignados al proceso: • Cuanto más marcos de página tenga un proceso, mayor será el tiempo entre los fallos de páginas. • El punto de inflexión se da cuando el proceso tiene todo su conjunto de trabajo en el almacenamiento primario. • Asignar marcos de página adicionales más allá del punto de inflexión no produce efectos significativos sobre el tiempo interfallos. Respecto del porcentaje de instrucciones de una página que son ejecutadas antes de transferirse el control a otra página, los valores experimentales obtenidos indican un máximo de 200 instrucciones por página de 1 kb 8 . 2.8 Porqué es Necesaria la Planificación de Discos En los sistemas de multiprogramación muchos procesos pueden estar generando peticiones de e / s sobre discos [4, Deitel]. • La generación de peticiones puede ser mucho más rápida que la atención de las mismas: — Se construyen líneas de espera o colas para cada dispositivo. — Para reducir el tiempo de búsqueda de registros se ordena la cola de peticiones: esto se denomina planificación de disco. 8 Ver Figura 2.7 de la página 54 [4, Deitel]. 54 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Figura 2.7: Comportamiento de un programa en la paginación. 2.8. PORQUÉ ES NECESARIA LA PLANIFICACIÓN DE DISCOS 55 La planificación de disco implica: • Un examen cuidadoso de las peticiones pendientes para determinar la forma más eficiente de servirlas. • Un análisis de las relaciones posicionales entre las peticiones en espera. • Un reordenamiento de la cola de peticiones para servirlas minimizando los movimientos mecánicos. Los tipos más comunes de planificación son: • Optimización de la búsqueda. • Optimización rotacional (latencia). Generalmente los tiempos de búsqueda superan a los de latencia, aunque la diferencia disminuye: • Muchos algoritmos de plani.cación se concentran en la reducción de los tiempos de búsqueda para un conjunto de peticiones. • Generalmente la reducción de la latencia recién tiene efectos bajo cargas de trabajo muy pesadas. Bajo condiciones de carga ligera (promedio bajo de longitud de la cola), es aceptable el desempeño del método FCFS (primero en llegar, primero en ser servido). Bajo condiciones de carga media o pesada, es recomendable un algoritmo de planificación de las colas de requerimientos. 2.8.1 Características Deseables de las Políticas de Planificación de Discos Los principales criterios de categorización de las políticas de plani.cación son [4, Deitel]: • Capacidad de ejecución. • Media del tiempo de respuesta. • Varianza de los tiempos de respuesta (predecibilidad). Una política de plani.cación debe intentar maximizar la capacidad de ejecución: • Maximizar el número de peticiones servidas por unidad de tiempo. • Minimizar la media del tiempo de respuesta. • Mejorar el rendimiento global, quizás a costa de las peticiones individuales. La planificación suele mejorar la imagen total al tiempo que reduce los niveles de servicio de ciertas peticiones: 56 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS • Se mide utilizando la varianza de los tiempos de respuesta. • La varianza es un término estadístico que indica hasta qué punto tienden a desviarse del promedio de todos los elementos los elementos individuales. • A menor varianza mayor predecibilidad. • Se desea una política de planificación que minimice la varianza, es decir que maximice la predecibilidad. • No debe haber peticiones que puedan experimentar niveles de servicio erráticos. 2.9 Algoritmos de Programación del Brazo del Disco En la mayoría de los discos, el tiempo de búsqueda supera al de retraso rotacional y al de transferencia [10, Tanenbaum], debido a ello, la reducción del tiempo promedio de búsqueda puede mejorar en gran medida el rendimiento del sistema. Si el manejador del disco utiliza el algoritmo primero en llegar primero en ser atendido (FCFS), poco se puede hacer para mejorar el tiempo de búsqueda. Es posible que mientras el brazo realiza una búsqueda para una solicitud, otros procesos generen otras solicitudes. Muchos manejadores tienen una tabla: • 2 • 2 • 2 El índice es el número de cilindro. Incluye las solicitudes pendientes para cada cilindro enlazadas entre sí en una lista ligada. Cuando concluye una búsqueda, el manejador del disco tiene la opción de elegir la siguiente solicitud a dar paso: — Se atiende primero la solicitud más cercana, para minimizar el tiempo de búsqueda. — Este algoritmo se denomina primero la búsqueda más corta (SSF: shortest seek rst). — Reduce a la mitad el número de movimientos del brazo en comparación con FCFS. Ej. de SSF: • Consideramos un disco de 40 cilindros. • Se presenta una solicitud de lectura de un bloque en el cilindro 11. • Durante la búsqueda, llegan solicitudes para los cilindros 1, 36, 16, 34, 9 y 12, en ese orden. • La secuencia de búsqueda SSF será: 12, 9, 16, 1, 34, 36. 2.9. ALGORITMOS DE PROGRAMACIÓN DEL BRAZO DEL DISCO 57 • Habrá un número de movimientos del brazo para un total de: — 111 cilindros según FCFS. — 61 cilindros según SSF. El algoritmo SSF tiene el siguiente problema: • El ingreso de nuevas solicitudes puede demorar la atención de las más antiguas. • Con un disco muy cargado, el brazo tenderá a permanecer a la mitad del disco la mayoría del tiempo, como consecuencia de ello las solicitudes lejanas a la mitad del disco tendrán un mal servicio. • Entran en con.icto los objetivos de: — Tiempo mínimo de respuesta. — Justicia en la atención. La solución a este problema la brinda el algoritmo del elevador (por su analogía con el ascensor o elevador): • Se mantiene el movimiento del brazo en la misma dirección, hasta que no tiene más solicitudes pendientes en esa dirección; entonces cambia de dirección. • El software debe conservar el bit de dirección actual. Ej. del algoritmo del elevador para el caso anterior, con el valor inicial arriba del bit de dirección: • El orden de servicio a los cilindros es: 12, 16, 34, 36, 9 y 1. • El número de movimientos del brazo corresponde a 60 cilindros. El algoritmo del elevador: • Ocasionalmente es mejor que el algoritmo SSF. • Generalmente es peor que SSF. • Dada cualquier colección de solicitudes, la cuota máxima del total de movimientos está fija, siendo el doble del número de cilindros. Una variante consiste en rastrear siempre en la misma dirección: • Luego de servir al cilindro con el número mayor: — El brazo pasa al cilindro de número menor con una solicitud pendiente. — Continúa su movimiento hacia arriba. 58 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Algunos controladores de disco permiten que el software inspeccione el número del sector activo debajo del cabezal: • Si dos o más solicitudes para el mismo cilindro están pendientes: — El manejador puede enviar una solicitud para el sector que pasará debajo del cabezal. — Se pueden hacer solicitudes consecutivas de distintas pistas de un mismo cilindro, sin generar un movimiento del brazo. Cuando existen varias unidades, se debe tener una tabla de solicitudes pendientes para cada unidad. Si una unidad está inactiva, deberá buscarse el cilindro siguiente necesario, si el controlador permite búsquedas traslapadas. Cuando termina la transferencia actual se veri.ca si las unidades están en la posición del cilindro correcto: • Si una o más unidades lo están, se puede iniciar la siguiente transferencia en una unidad ya posicionada. • Si ninguno de los brazos está posicionado, el manejador: — Debe realizar una nueva búsqueda en la unidad que terminó la transferencia. — Debe esperar hasta la siguiente interrupción para ver cuál brazo se posiciona primero. Generalmente, las mejoras tecnológicas de los discos: • Acortan los tiempos de búsqueda (seek). • No acortan los tiempos de demora rotacional (search). • En algunos discos, el tiempo promedio de búsqueda ya es menor que el retraso rotacional. • El factor dominante será el retraso rotacional, por lo tanto, los algoritmos que optimizan los tiempos de búsqueda (como el algoritmo del elevador) perderán importancia frente a los algoritmos que optimicen el retraso rotacional. Una tecnología importante es la que permite el trabajo conjunto de varios discos. Una con.guración interesante es la de treinta y ocho (38) unidades ejecutándose en paralelo. Cuando se realiza una operación de lectura: • Ingresan a la cpu 38 bit a la vez, uno por cada unidad. • Los 38 bits conforman una palabra de 32 bits junto con 6 bits para verificación. • Los bits 1, 2, 4, 8, 16 y 32 se utilizan como bits de paridad. 2.10. OPTIMIZACIÓN DE LA BÚSQUEDA EN DISCOS 59 • La palabra de 38 bits se puede codificar mediante el código Hamming, que es un código corrector de errores. • Si una unidad sale de servicio: — Se pierde un bit de cada palabra. — El sistema puede continuar trabajando; se debe a que los códigos Hamming se pueden recuperar de un bit perdido. Este diseño se conoce como RAID; siglas en inglés de .arreglo redundante de discos no costosos. 2.10 Optimización de la Búsqueda en Discos Las estrategias más comunes de optimización de la búsqueda son las siguientes [4, Deitel]: • FCFS. • SSTF. • SCAN. • SCAN de N - Pasos. • C - SCAN. • Esquema Eschenbach. 2.10.1 Planificación FCFS (Primero en Llegar, Primero en Ser Servido) Una petición no puede ser desplazada por la llegada de una petición con prioridad más alta. No hay reordenamiento de la cola de peticiones pendientes. Se ignoran las relaciones posicionales entre las peticiones pendientes. Ofrece una varianza pequeña aunque perjudica a las peticiones situadas al final de la cola. 2.10.2 Planificación SSTF (Menor Tiempo de Búsqueda Primero) El brazo del disco se sitúa en la siguiente petición que minimice el movimiento del brazo. No respeta el orden de llegada de las peticiones a la cola. Tiende a favorecer a las pistas del centro del disco. La media de tiempos de respuesta tiende a ser más baja que con FCFS, para cargas moderadas. Las varianzas tienden a ser mayores que con FCFS por el efecto de las pistas interiores y exteriores. 60 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS 2.10.3 Planificación SCAN El brazo del disco se desplaza sirviendo a todas las peticiones que encuentra a su paso. Cambia de dirección cuando ya no hay peticiones pendientes en la dirección actual. Ha sido la base de la mayoría de las estrategias de plani.cación implementadas. Elimina las discriminaciones de SSTF y tiene menor varianza. Las pistas exteriores son menos visitadas que las intermedias, pero no es tan grave como con SSTF. 2.10.4 Planificación SCAN de N - Pasos La estrategia de movimiento del brazo es como en SCAN; solo da servicio a las peticiones que se encuentran en espera cuando comienza un recorrido particular. Las peticiones que llegan durante un recorrido son agrupadas y ordenadas y serán atendidas durante el recorrido de regreso. Posee menor varianza de los tiempos de respuesta si se compara con las planificaciones SSTF y SCAN convencionales. 2.10.5 Planificación C - SCAN (Búsqueda Circular) El brazo se mueve del cilindro exterior al interior, sirviendo a las peticiones sobre una base de búsqueda más corta. Finalizado el recorrido hacia el interior, salta a la petición más cercana al cilindro exterior y reanuda su desplazamiento hacia el interior. No discrimina a los cilindros exterior e interior. La varianza de los tiempos de respuesta es muy pequeña. 2.10.6 Esquema Eschenbach El brazo del disco se mueve como en C - SCAN, pero: • Las peticiones se reordenan para ser servidas dentro de un cilindro para tomar ventaja de la posición rotacional. • Si dos peticiones trasladan posiciones de sectores dentro de un cilindro, solo se sirve una en el movimiento actual del brazo del disco. Esta estrategia tiene en cuenta el retraso rotacional. 2.10.7 Conclusiones Mediante trabajos de simulación y de laboratorio se demostró lo siguiente: • La estrategia SCAN es la mejor con carga baja. • La estrategia C - SCAN es la mejor con cargas medias y pesadas. • La estrategia C - SCAN con optimización rotacional es la mejor para cargas muy pesadas (mejor que la estrategia Eschenbach inclusive). 2.11. OPTIMIZACIÓN ROTACIONAL EN DISCOS 2.11 61 Optimización Rotacional en Discos En condiciones de carga pesada, las probabilidades de que ocurran referencias al mismo cilindro aumentan, por ello resulta útil considerar la optimización rotacional además de la optimización de búsqueda . La optimización rotacional es de uso común en dispositivos de cabezas fijas. La estrategia utilizada es la SLTF (tiempo de latencia más corto primero): • Situado el brazo del disco en un cilindro: — . Examina todas las peticiones sobre el cilindro. — . Sirve primero a la que tiene el retraso rotacional más corto. 2.12 Consideraciones de los Discos Sobre los Sistemas Los principales interrogantes son [4, Deitel]: • Cuándo es útil la plani.cación de disco. • Cuándo puede degradar el rendimiento. El almacenamiento en disco como un recurso limitador. La planificación de disco puede mejorar el rendimiento y eliminar el embotellamiento, que se produce cuando se concentran grandes cargas de peticiones sobre relativamente pocos discos o pocos cilindros de un disco. Nivel de multiprogramación Generalmente la planificación es efectiva en sistemas de tiempo compartido con un nivel alto de multiprogramación. Subsistemas de discos múltiples Frecuentemente la cpu está conectada mediante canales (o bus) a dispositivos controladores, los que están conectados a las unidades de discos. El embotellamiento puede producirse en algún disco, algún controlador o en algún canal. Existe software específico para: • Medir la actividad. • Detectar dónde se produce el embotellamiento. Para eliminar ciertos embotellamientos puede ser necesaria una recon.guración del hardware: • Agregar canales, controladores, dispositivos. • Cambiar dispositivos de un controlador a otro. • Cambiar controladores de un canal a otro. 62 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS Para ayudar a reducir la congestión del canal, muchos sistemas han incorporado la técnica de examen (sensado) de posición rotacional (RPS): • Reduce el tiempo durante el cual un canal se encuentra ocupado en la búsqueda de un registro. • RPS permite al canal quedar libre justo hasta antes de que el registro se encuentre debajo de la cabeza de lectura - grabación apropiada. • RPS permite varias peticiones activas al mismo tiempo en un solo canal, incrementando la performance. Distribución de peticiones no uniformes Son muy comunes en ciertas situaciones reales. Son frecuentes en procesos secuenciales de archivos secuenciales, para los que se afectaron cilindros adyacentes inmediatos. Generalmente en estos casos las búsquedas son cortas y la planificación de disco será de poca utilidad. Técnicas de organización de archivos Los métodos de organización y acceso de archivos, así como los DBMS (manejadores de bases de datos): • 2 • 2 Son muy convenientes desde el punto de vista de las aplicaciones y del usuario. Pueden generar complicaciones en la implementación y el rendimiento, puesto que significar un gran número de operaciones de e / s. 2.13 Manejo de Errores en Discos Algunos de los errores más comunes en discos son [10, Tanenbaum]: • Error de programación: — Ej.: Solicitar un sector no existente. • Error temporal en la suma de verificación: — Ej.: Provocado por polvo en la cabeza. • Error permanente en la suma de verificación: — Ej.: Un bloque del disco dañado físicamente. • Error de búsqueda: — Ej.: El brazo se envía al cilindro 6 pero va al 7. • Error del controlador: 2.13. MANEJO DE ERRORES EN DISCOS 63 — Ej.: El controlador no acepta los comandos. El manejador del disco debe controlar los errores de la mejor manera posible. La mayoría de los controladores: • Verifican los parámetros que se les proporcionan. • Informan si no son válidos. Respecto de los errores temporales en la suma de verificación: • Generalmente se eliminan al repetir la operación. • Si persisten, el bloque debe ser marcado como un bloque defectuoso, para que el software lo evite. Otra posibilidad es que controladores inteligentes reserven cierta cantidad de pistas: • Serán asignadas en reemplazo de pistas defectuosas. • Una tabla asocia las pistas defectuosas con las pistas de repuesto: — . Está alojada en la memoria interna del controlador y en el disco. — . La sustitución es transparente para el manejador. — . Puede afectarse el desempeño de los algoritmos de búsqueda, como el del elevador,ya que el controlador utiliza pistas físicamente distintas de las solicitadas. 2.13.1 Ocultamiento de Una Pista a la Vez en Discos Generalmente el tiempo de búsqueda supera al de rotación y transferencia (aunque esto se esta equilibrando) [10, Tanenbaum]. Una vez resuelta la búsqueda del cilindro correspondiente, no es muy importante si se lee un sector o toda la pista: • Especialmente en dispositivos con sensibilidad rotacional (RPS): — El manejador puede ver que sector se encuentra debajo de la cabeza y puede enviar una solicitud del siguiente sector: ∗ Permite leer una pista en un tiempo de rotación. ∗ De lo contrario se tardaría, en promedio, un tiempo de rotación más un tiempo de sector, para leer un solo sector. • Algunos manejadores aprovechan esto mediante un caché secreto de una pista a la vez : — Es desconocido por el software independiente del dispositivo. — Si se necesita un sector del caché, no es necesaria una transferencia del disco. — Las principales desventajas de este ocultamiento de una pista a la vez son: 64 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS ∗ Complejidad del software. ∗ Requerimientos de espacio para buers. ∗ Las transferencias del caché al programa que hace la llamada: · Las debe realizar la cpu mediante un ciclo programado. · No las puede hacer el hardware DMA. — Algunos controladores realizan el ocultamiento de una pista a la vez en su propia memoria interna: ∗ Resulta transparente al manejador. ∗ Las transferencias entre el controlador y la memoria pueden utilizar DMA. 2.14 Discos en RAM Utilizan una parte de la memoria principal asignada con anterioridad para almacenar los bloques [10, Tanenbaum]. Tienen la ventaja del acceso instantáneo: • No hay demora rotacional o debida a las búsquedas. • Son adecuados para el almacenamiento de programas o datos con accesos muy frecuentes. Los bloques de almacenamiento tienen el mismo tamaño que en los discos reales. Cuando el manejador debe leer de o escribir en un bloque de un disco en RAM, calcula el lugar de la memoria donde se encuentra el bloque solicitado y lee o escribe en el mismo. 2.15 Relojes Los relojes o cronómetros son esenciales para la operación de sistemas de tiempo compartido [10, Tanenbaum]. Registran la hora del día. Evitan que un proceso monopolice la cpu. El software para reloj toma generalmente la forma de un manejador de dispositivo, aunque no es un dispositivo de bloque ni de caracter. Los relojes más sencillo trabajan con la línea de corriente eléctrica de 110 o 220 voltios y provocan una interrupción por cada ciclo de voltaje, a 50 o 60 hz. Otro tipo de relojes consta de tres componentes: • Un oscilador de cristal, un contador y un registro. • Una pieza de cristal de cuarzo se monta en una estructura bajo tensión: — Genera una señal periódica de muy alta precisión, generalmente entre 5 y 100 mhz. — La señal se alimenta en el contador para que cuente en forma descendente hasta cero. 2.16. TERMINALES 65 — Cuando el contador llega a cero, provoca una interrupción de la cpu. Los relojes programables tienen varios modos de operación: • Modo de una instancia: — Cuando el reloj se inicializa, copia el valor del registro en el contador. — Decrementa el contador en cada pulso del cristal. — Cuando el contador llega a cero provoca una interrupción y se detiene hasta ser nuevamente inicializado por el software. • Modo de onda cuadrada: — Luego de llegar a cero y provocar la interrupción, el registro se copia de manera automática en el contador. — Todo el programa se repite en forma indefinida. — Las interrupciones periódicas se llaman marcas del reloj. La ventaja del reloj programable es que su frecuencia de interrupción puede ser controlada por el software. Las principales funciones del software manejador del reloj son: • Mantener la hora del día o tiempo real. • Evitar que los procesos se ejecuten durante más tiempo del permitido. • Mantener un registro del uso de la cpu. • Controlar llamadas al sistema tipo .alarm. por parte de los procesos del usuario. • Proporcionar cronómetros guardianes de partes del propio sistema. • Realizar resúmenes, monitoreo y recolección de estadísticas. El software manejador del reloj puede tener que simular varios relojes virtuales con un único reloj físico. 2.16 Terminales Las terminales tienen gran número de formas distintas [10, Tanenbaum] : • El manejador de la terminal debe ocultar estas diferencias. • La parte independiente del dispositivo en el S. O. y los programas del usuario no se tienen que reescribir para cada tipo de terminal. Desde el punto de vista del S. O. se las puede clasi.car en: 66 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS • Interfaz RS-232: — Hardcopy (terminales de impresión). — TTY de vidrio (terminales de video). — Inteligente (computadoras con cpu y memoria). • Interfaz mapeada a memoria: — Orientada a caracteres. — Orientada a bits. Las terminales RS-232 poseen un teclado y un monitor que se comunican mediante una interfaz serial, un bit a la vez; las conversiones de bits a bytes y viceversa las efectúan los chips uart (transmisores - receptores asíncronos universales). Las terminales mapeadas a memoria: No se comunican mediante una línea serial. • Poseen una interfaz mediante una memoria especial llamada video RAM: — Forma parte del espacio de direcciones de la computadora. — La cpu se dirige a ella como al resto de la memoria. — En la tarjeta de video RAM hay un chip llamado controlador de video: ∗ Extrae bytes del video RAM y genera la señal de video utilizada para manejar la pantalla. ∗ El monitor genera un rayo de electrones que recorre la pantalla pintando líneas. ∗ Cada línea está constituida por un cierto número de puntos o pixeles. ∗ La señal del controlador de video modula el rayo de electrones y determina si un pixel debe estar o no iluminado. ∗ Los monitores de color poseen tres rayos (rojo, verde y azul) que se modulan independientemente. En las pantallas mapeadas a caracteres: Cada caracter en la pantalla equivale a dos caracteres de RAM: — . Uno aloja al código (ASCII) del caracter por exhibir. — . Otro es el byte de atributo, necesario para determinar el color, el video inverso, el parpadeo, etc. En las terminales mapeadas a bits: • Se utiliza el mismo principio. • Cada bit en el video RAM controla en forma directa un solo pixel de la pantalla. 2.17. PROCESOS Y PROCESADORES EN SISTEMAS DISTRIBUIDOS 67 • Permite una completa .exibilidad en los tipos y tamaños de caracteres, varias ventanas y grá.cos arbitrarios. Con las pantallas mapeadas a memoria, el teclado se desacopla totalmente de la pantalla : El teclado dispone de su propio manejador. • El manejador del teclado puede operar en modo caracter o en modo línea. Las terminales pueden operar con una estructura central de buffers o con buffers exclusivos para cada terminal. Frecuentemente los manejadores de terminales soportan operaciones tales como: • Mover el cursor hacia arriba, abajo, a la izquierda o a la derecha una posición. • Mover el cursor a x,y. • Insertar un caracter o una línea en el cursor. • Eliminar un caracter o una línea en el cursor. • Recorrer la pantalla hacia arriba o hacia abajo .n. líneas. • Limpiar la pantalla desde el cursor hacia el final de la línea o hasta el final de la pantalla. • Trabajar en modo de video inverso, subrayado, parpadeo o normal. • Crear, construir, mover o controlar las ventanas. 2.17 Procesos y Procesadores en Sistemas Distribuidos 2.18 Introducción a los Hilos (Threads) Muchos S. O. distribuidos soportan múltiples hilos de control dentro de un proceso que [11, Tanenbaum]: Comparten un único espacio de direcciones. • Se ejecutan quasi - paralelamente como si fueran procesos independientes. Ej.: servidor de archivos que debe bloquearse ocasionalmente en espera de acceso al disco: • Si tiene varios hilos de control podría ejecutar un segundo hilo mientras el primero espera: — El resultado sería mejor rendimiento y desempeño. — No se logra esto con procesos servidores independientes puesto que deben compartir un buffer caché común y deben estar en el mismo espacio de direcciones. 68 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS En muchos sentidos los hilos son como miniprocesos: • Cada hilo: — Se ejecuta en forma estrictamente secuencial. — Tiene su propio contador de programa y una pila para llevar un registro de su posición. • Los hilos comparten la cpu de la misma forma que lo hacen los procesos: — Secuencialmente, en tiempo compartido. • Solo en un multiprocesador se pueden ejecutar realmente en paralelo. • Los hilos pueden crear hilos hijos. • Mientras un hilo está bloqueado se puede ejecutar otro hilo del mismo proceso. Los distintos hilos de un proceso comparten un espacio de direcciones, el conjunto de archivos abiertos, los procesos hijos, cronómetros, señales, etc. Los hilos pueden tener distintos estados: en ejecución, bloqueado, listo, terminado. 2.18.1 Uso de Hilos Los hilos permiten la combinación del paralelismo con la ejecución secuencial y el bloqueo de las llamadas al sistema [11, Tanenbaum] . Consideramos el ejemplo del servidor de archivos con sus posibles organizaciones para muchos hilos de ejecución. Iniciamos con el modelo servidor / trabajador: • Un hilo, el servidor, lee las solicitudes de trabajo en el buzón del sistema. • Elige a un hilo trabajador inactivo (bloqueado) y le envía la solicitud, despertándolo. El hilo trabajador verifica si puede satisfacer la solicitud por medio del bloque caché compartido, al que tienen acceso todos los hilos. • Si no envía un mensaje al disco para obtener el bloque necesario y se duerme esperando el fin de la operación. • Se llama: — Al planificador y se inicializa otro hilo, que tal vez sea el servidor, para pedir más trabajo; o. — A otro trabajador listo para realizar un trabajo. Los hilos ganan un desempeño considerable pero cada uno de ellos se programa en forma secuencial. Otro modelo es el de equipo: 2.18. INTRODUCCIÓN A LOS HILOS (THREADS) 69 • Todos los hilos son iguales y cada uno obtiene y procesa sus propias solicitudes. • No hay servidor. • Se utiliza una cola de trabajo que contiene todos los trabajos pendientes, que son trabajos que los hilos no han podido manejar. • Un hilo debe veri.car primero la cola de trabajo antes de buscar en el buzón del sistema. Un tercer modelo es el de entubamiento: El primer hilo genera ciertos datos y los trans.ere al siguiente para su procesamiento. • 2 Los datos pasan de hilo en hilo y en cada etapa se lleva a cabo cierto procesamiento. Un programa diseñado adecuadamente y que utilice hilos debe funcionar bien: • 2 En una única cpu con hilos compartidos. • 2 En un verdadero multiprocesador. 2.18.2 Aspectos del Diseño de un Paquete de Hilos Un conjunto de primitivas relacionadas con los hilos (ej.: llamadas a biblioteca) disponibles para los usuarios se llama un .paquete de hilos. [11, Tanenbaum] . Respecto del manejo de los hilos se tienen hilos estáticos e hilos dinámicos. En un diseño estático: • Se elige el número de hilos al escribir el programa o durante su compilación. • Cada uno de ellos tiene asociada una pila .ja. • Se logra simplicidad pero también in.exibilidad En un diseño dinámico: • Se permite la creación y destrucción de los hilos durante la ejecución. • La llamada para la creación de hilos determina: — El programa principal del hilo. — Un tamaño de pila. — Una prioridad de planificación, etc. • La llamada generalmente regresa un identi.cador de hilo: — Se usará en las posteriores llamadas relacionadas al hilo. • Un proceso: 70 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS — Se inicia con un solo hilo. — Puede crear el número necesario de hilos. — Los hilos pueden concluir: • Por su cuenta, al terminar su trabajo. • Por su eliminación desde el exterior. — Los hilos comparten una memoria común: • Contiene datos que los distintos hilos comparten. • El acceso generalmente se controla mediante regiones críticas. 2.19 Implantación de un Paquete de Hilos Un paquete de hilos se puede implantar en el espacio [11, Tanenbaum]: • Del usuario. • Del núcleo. Implantación del paquete de hilos en el espacio del usuario: • El núcleo no sabe de su existencia. • El núcleo maneja procesos con un único hilo. • No requiere soporte de hilos por parte del S. O. • Los hilos se ejecutan en un sistema de tiempo de ejecución: — Es un grupo de procedimientos que manejan los hilos. • Cuando un hilo ejecuta una llamada al sistema o cualquier acción que pueda provocar su suspensión: • Llama a un procedimiento del sistema de tiempo de ejecución. • El procedimiento veri.ca si hay que suspender al hilo, en cuyo caso: ∗ Almacena los registros del hilo en una tabla. ∗ Busca un hilo no bloqueado para ejecutarlo. ∗ Vuelve a cargar los registros de la máquina con los valores resguardados del nuevo hilo. • Las principales ventajas son: — El intercambio de hilos es más rápido que si se utilizaran los señalamientos al núcleo. 2.19. IMPLANTACIÓN DE UN PAQUETE DE HILOS 71 — Cada proceso puede tener su propio algoritmo adaptado de planificación de hilos. — Tienen una mejor escalabilidad para un número muy grande de hilos, ya que no afectan al núcleo con tablas y bloques de control (pila). Implantación del paquete de hilos en el espacio del núcleo: • No se necesita un sistema de tiempo de ejecución. • Para cada proceso el núcleo tiene una tabla con una entrada por cada hilo que contiene: — Los registros, estados, prioridades y demás información relativa al hilo. • Todas las llamadas que pueden bloquear un hilo se implantan como llamadas al sistema: — Significa un costo mayor (en recursos y tiempo). • Cuando un hilo se bloquea, el núcleo puede ejecutar: — Otro hilo listo del mismo proceso. — Un hilo de otro proceso: ∗ Con los hilos a nivel usuario el sistema de tiempo de ejecución mantiene en ejecución los hilos de su propio proceso hasta que: · El núcleo les retira la cpu, o. · No hay hilos listos. Un problema fundamental de los paquetes de hilos a nivel usuario es el de las llamadas al sistema con bloqueo: • No se puede permitir que el hilo realmente realice la llamada al sistema: — Detendría a todos los hilos del proceso. — Un hilo bloqueado no debe afectar a los demás. • Una solución es agregar código junto a la llamada al sistema para verificar si la misma no generaría bloqueo: — . Se efectuaría la llamada al sistema solo si la veri.cación da o.k. — . El código adicional suele llamarse jacket. Otro problema de los paquetes de hilos a nivel usuario es que si un hilo comienza su ejecución no puede ejecutarse ningún otro hilo de ese proceso, salvo que el hilo entregue voluntariamente la cpu. Un problema adicional para los hilos a nivel usuario es que generalmente los programadores desean los hilos en aplicaciones donde los hilos se bloquean a menudo: • Ej.: servidor de archivos con varios hilos. 72 CAPÍTULO 2. FUNDAMENTOS TEÓRICOS 2.20 Hilos y RPC Es común que los sistemas distribuidos utilicen RPC e hilos [11, Tanenbaum]. Al iniciar un hilo servidor, S, éste exporta su interfaz al informarle de ésta al núcleo; la interfaz de.ne los procedimientos que puede llamar, sus parámetros, etc. Al iniciar un hilo cliente, C, éste importa la interfaz del núcleo: • Se le proporciona un identi.cador especial para utilizarlo en la llamada. • El núcleo sabe que C llamará posteriormente a S: — Crea estructuras de datos especiales para prepararse para la llamada. Una de las estructuras es una pila de argumentos compartida por C y S, que se asocia de manera lectura / escritura en ambos espacios de direcciones. Para llamar al servidor, C : • Coloca sus argumentos en la pila compartida mediante el procedimiento normal de transferencia. • Hace un señalamiento al núcleo colocando un identificador especial en un registro. El núcleo: • Detecta esto y deduce que es una llamada local. • Modifica el mapa de memoria del cliente para colocar éste en el espacio de direcciones del servidor. • Inicia el hilo cliente, al ejecutar el procedimiento del servidor La llamada se efectúa de tal forma que: • Los argumentos se encuentran ya en su lugar: — No es necesario su copiado u ordenamiento. — La RPC local se puede realizar más rápido de esta manera. Capítulo 3 JAVA 3.1 Introducción al Lenguaje Java es un lenguaje orientado a objetos. Esto significa que posee ciertas características que hoy día se consideran estándares en los lenguajes OO: • Objetos. • Clases. • Métodos. • Subclases. • Herencia simple. • Enlace dinámico. • Encapsulamiento. Para programar orientado a objetos es necesario primero diseñar un conjunto de clases. La claridad, eficiencia y mantenibilidad del programa resultante dependerá principalmente de la calidad del diseño de clases. Un buen diseño de clases significará una gran economía en tiempo de desarrollo y mantención. Lamentablemente se necesita mucha habilidad y experiencia para lograr diseños de clases de calidad. Un mal diseño de clases puede llevar a programas OO de peor calidad y de más alto costo que el programa equivalente no OO [8, Castillo-Cobo-Solares]. Por qué entonces la ventaja de programar en un lenguaje OO, si se requiere una experiencia que probablemente una persona nunca tendrá el tiempo de práctica para llegar a obtenerla. La respuesta a este interrogante es que Java es un lenguaje multiparadigma (como muchos otros lenguajes de programación). No se necesita hacer un diseño de clases para programar una aplicación de mil líneas. Entonces otro interrogante podrá ser porque no programar con otro lenguaje más simples, como puede ser Visual Basic, si no se necesita que sea OO. La respuesta a ésto es la gran ventaja de un lenguaje OO, que son las bibliotecas de clases que se pueden construir para la aplicación [6, Joyanes Aguilar-Zahonero Martínez]. Una biblioteca de 73 74 CAPÍTULO 3. JAVA clases cumple el mismo objetivo de una biblioteca de procedimientos en una lenguaje como C. Sin embargo: Una biblioteca de clases es mucho más fácil de usar que una biblioteca de procedimientos, incluso para programadores sin experiencia en orientación a objetos. Esto se debe a que las clases ofrecen mecanismos de abstracción más eficaces que los procedimientos. Se puede distinguir entre varios tipos de programadores en Java: — El diseñador de clases: Es el encargado de definir qué clases ofrece una biblioteca y cuál es la funcionalidad que se espera de estas clases. Esta persona tiene que ser muy hábil y de mucha experiencia. Un diseño equivocado puede conducir a clases que son incomprensibles para los clientes de la biblioteca. — El programador de clases de biblioteca: Sólo programa la clases especificadas por el diseñador de clases. Esta persona debe entender orientación a objetos, pero no requiere mayor experiencia en diseño de clases. — El cliente de bibliotecas: Es el programador de aplicaciones. Él sólo usa las clases que otros han diseñado y programado. Como en el caso anterior necesita entender orientación a objetos y conocer la biblioteca que va usar, pero no necesita mayor experiencia. Tanto programadores de clases como clientes de bibliotecas pueden llegar a convertirse en buenos diseñadores de clases en la medida que adquieran experiencia, comparando los diseños de las bibliotecas que utilicen. Por lo tanto es importante destacar que no se necesita gran experiencia en diseño orientado a objetos para poder aprovechar las ventajas de la orientación a objetos [2, Joyanes Aguilar]. 3.1.1 Bibliotecas de Clases Estándares de Java Toda implementación de Java debe tener las siguientes bibliotecas de clases: • Manejo de archivos. • Comunicación de datos. • Acceso a la red Internet.. • Acceso a bases de datos. • Interfaces gráficas. La interfaz de programación de estas clases es estándar, es decir en todas ellas las operaciones se invocan con el mismo nombre y los mismos argumentos. 3.1.2 Java es Multiplataforma Los programas en Java pueden ejecutarse en cualquiera de las siguientes plataformas, sin necesidad de hacer cambios: 3.1. INTRODUCCIÓN AL LENGUAJE 75 Windows/95 y /NT. Power/Mac. Unix (Solaris, Silicon Graphics, ...). La compatibilidad es total: A nivel de fuentes: El lenguaje es exactamente el mismo en todas las plataformas. A nivel de bibliotecas: En todas las plataformas están presentes las mismas bibliotecas estándares. A nivel del código compilado: el código intermedio que genera el compilador es el mismo para todas las plataformas. Lo que cambia es el intérprete del código intermedio. 3.1.3 Características del Lenguaje Java • Robustez En Java no se pueden cometer los cuatro errores que se mencionarán a continuación: Java siempre chequea los índices al acceder a un arreglo. Java realiza chequeo de tipos durante la compilación (al igual que C). En una asignación entre punteros el compilador verifica que los tipos sean compatibles. Además, Java realiza chequeo de tipos durante la ejecución (cosa que C y C++ no hacen). Cuando un programa usa un cast para acceder a un objeto como si fuese de un tipo específico, se verifica durante la ejecución que el objeto en cuestión sea compatible con el cast que se le aplica. Si el objeto no es compatible, entonces se levanta una excepción que informa al programador la línea exacta en donde está la fuente del error. Java posee un recolector de basuras que administra automáticamente la memoria. Es el recolector el que determina cuando se puede liberar el espacio ocupado por un objeto. El programador no puede liberar explícitamente el espacio ocupado por un objeto. Java no posee aritmética de punteros, porque es una propiedad que no se necesita para programar aplicaciones. En C sólo se necesita la aritmética de punteros para programa malloc/free o para programar el núcleo del sistema operativo. Por lo tanto Java no es un lenguaje para hacer sistemas operativos o administradores de memoria, pero sí es un excelente lenguaje para programar aplicaciones. • Flexibilidad Java combina flexibilidad, robustez y legibilidad gracias a una mezcla de chequeo de tipos durante la compilación y durante la ejecución. En Java se pueden tener punteros a objetos de un tipo específico y también se pueden tener punteros a objetos de cualquier tipo. Estos punteros se pueden convertir a punteros de un tipo específico aplicando un cast, en cuyo caso se chequea en tiempo de ejecución de que el objeto sea de un tipo compatible. El programador usa entonces punteros de tipo específico en la mayoría de los casos con el fin de ganar legibilidad y en unos pocos casos usa punteros a tipos desconocidos cuando necesita tener flexibilidad. Por lo tanto Java combina la robustez de Pascal con la flexibilidad de Lisp, sin que lo programas pierdan legibilidad en ningún caso. • Administración Automática de la Memoria 76 CAPÍTULO 3. JAVA En Java los programadores no necesitan preocuparse de liberar un trozo de memoria cuando ya no lo necesitan. Es el recolector de basuras el que determina cuando se puede liberar la memoria ocupada por un objeto. Un recolector de basuras es un gran aporte a la productividad. Se ha estudiado en casos concretos que los programadores han dedicado un 40% del tiempo de desarrollo a determinar en qué momento se puede liberar un trozo de memoria. Además este porcentaje de tiempo aumenta a medida que aumenta la complejidad del software en desarrollo. Es relativamente sencillo liberar correctamente la memoria en un programa de 1000 líneas. Sin embargo, es difícil hacerlo en un programa de 10000 líneas. Y se puede postular que es imposible liberar correctamente la memoria en un programa de 100000 líneas. Para entender mejor esta afirmación, se podría suponer que se realizó un programa de 1000 líneas hace un par de meses y ahora se necesita hacer algunas modificaciones. Ahora, para esta altura ya se habrán olvidado gran parte de los detalles de la lógica de ese programa y no será sencillo determinar si un puntero referencia un objeto que todavía existe, o si ya fue liberado. Peor aún, supóngase que el programa fue hecho por otra persona y evalúe cuán probable es cometer errores de memoria al tratar de modificar ese programa. Volviendo al caso de un programa de 100000 líneas. Este tipo de programas los desarrolla un grupo de programadores que pueden tomar años en terminarlo. Cada programador desarrolla un módulo que eventualmente utiliza objetos de otros módulos desarrollados por otros programadores. Entonces, quién libera la memoria de estos objetos, cómo se ponen de acuerdo los programadores sobre cuándo y quién libera un objeto compartido, o cómo probar el programa completo ante las infinitas condiciones de borde que pueden existir en un programa de 100000 líneas. Es inevitable que la fase de prueba dejará pasar errores en el manejo de memoria que sólo serán detectados más tarde por el usuario final. Probablemente se incorporan otros errores en la fase de mantención. Resumiendo, se puede concluir que: todo programa de 100000 líneas que libera explícitamente la memoria tiene errores latentes, sin un recolector de basuras no hay verdadera modularidad y un recolector de basuras resuelve todos los problemas de manejo de memoria en forma trivial. El interrogante sería cuál es el impacto de un recolector de basura en el desempeño de un programa. El sobrecosto de la recolección de basuras no es superior al 100%. Es decir si se tiene un programa que libera explícitamente la memoria y que toma tiempo X, el mismo programa modificado de modo que utilice un recolector de basuras para liberar la memoria tomará un tiempo no superior a 2X. Este sobrecosto no es importante si se considera el periódico incremento en la velocidad de los procesadores. El impacto que un recolector de basura en el tiempo de desarrollo y en la confiabilidad del software resultante es muchos más importante que la pérdida en eficiencia. 3.2 Estructura General de un Programa Java En el siguiente ejemplo se presenta la estructura habitual de un programa realizado en cualquier lenguaje orientado a objetos u OOP (Object Oriented Programming), y en par- 3.3. CONCEPTOS BÁSICOS 77 ticular en el lenguaje Java: import java.awt.*; import java.lang.String; import java.lang.Integer; import java.awt.event.WindowEvent; import java.util.*; import java.awt.TextField; public class Simu extends Frame implements ActionListener,ItemListener{ MenuBar barra; m1 =new Menu(“Archivo”); barra.add(m1); m2 =new Menu(“Ver”); barra.add(m2); .... public static void main(String argv [ ]){ Simu menus = new Simu(); menus.setTitle(“Simulación de Redes”); menus.setVisible(true); } } Aparece una clase que contiene el programa principal Simu (aquel que contiene la función main()) y algunas clases de usuario (las específicas de la aplicación que se está desarrollando) que son utilizadas por el programa principal. La aplicación se ejecuta por medio del nombre de la clase que contiene la función main(). Las clases de Java se agrupan en packages, que son librerías de clases. Si las clases no se definen como pertenecientes a un package, se utiliza un package por defecto (default) que es el directorio activo. 3.3 3.3.1 Conceptos Básicos Clase Una clase es una agrupación de datos (variables o campos) y de funciones (métodos) que operan sobre esos datos. A estos datos y funciones pertenecientes a una clase se les denomina variables y métodos o funciones miembro. La programación orientada a objetos se basa en la programación de clases [2, Joyanes]. Un programa se construye a partir de un conjunto de clases. Una vez definida e implementada una clase, es posible declarar elementos de esta clase de modo similar a como se declaran las variables del lenguaje (int, double, String). Los elementos declarados de una clase se denominan objetos de la clase. De una única clase se pueden declarar o crear numerosos objetos. La clase es lo genérico: es el patrón o modelo 78 CAPÍTULO 3. JAVA para crear objetos. Cada objeto tiene sus propias copias de las variables miembro, con sus propios valores, en general distintos de los demás objetos de la clase. Las clases pueden tener variables static, que son propias de la clase y no de cada objeto [?, Bosz]. Ejemplo: public abstract class FuncionActivacion implements Cloneable,Serializable{ /*constructor sin argumentos que permite la herencia */ public FuncionActivacion () { } } 3.3.2 Herencia La herencia permite que se puedan definir nuevas clases basadas en clases existentes, lo cual facilita reutilizar código previamente desarrollado. Si una clase deriva de otra (extends) hereda todas sus variables y métodos. La clase derivada puede añadir nuevas variables y métodos y/o redefinir las variables y métodos heredados. En Java, a diferencia de otros lenguajes orientados a objetos, una clase sólo puede derivar de una única clase, con lo cual no es posible realizar herencia múltiple en base a clases. Sin embargo es posible “simular” la herencia múltiple en base a las interfaces. 3.3.3 Interface Una interface es un conjunto de declaraciones de funciones. Si una clase implementa (implements) una interface, debe definir todas las funciones especificadas por la interface. Una clase puede implementar más de una interface, representando una forma alternativa de la herencia múltiple. Una interface puede derivar de otra o incluso de varias interfaces, en cuyo caso incorpora todos los métodos de las interfaces de las que deriva. Ejemplo: La clase TangenteHiperbolica se extiende de la clase FuncionActivacion que implementa la interface Serializable. /*función de activación tangente hiperbólica */ public class TangenteHiperbolica extends FuncionActivacion implements Serializable{ /*constructor sin argumentos */ public TangenteHiperbolica () { } } 3.4. VARIABLES DENTRO DEL LENGUAJE JAVA 3.3.4 79 Package Un package es una agrupación de clases. Existen una serie de packages incluidos en el lenguaje. Además el programador puede crear sus propios packages. Todas las clases que formen parte de un package deben estar en el mismo directorio. Los packages se utilizan con las siguientes finalidades: 1. Para agrupar clases relacionadas. 2. Para evitar conflictos de nombres. En caso de conflicto de nombres entre clases importadas, el compilador obliga a cualificar en el código los nombres de dichas clases con el nombre del package. 3. Para ayudar en el control de la accesibilidad de clases y miembros. Por las razones citadas, durante la etapa de Diseño del Software desarrollado, se ha decido crear dos paquetes, calculos e interfase, utilizando la sentencia package. package myprojects.simu; import myprojects.calculos.*; import myprojects.interfase.*; 3.3.5 La Jerarquía de Clases de Java (API) Durante la generación de código en Java, es recomendable y casi necesario tener siempre a la vista la documentación on-line del API de Java 1.1 o Java 1.2. En dicha documentación es posible ver tanto la jerarquía de clases, es decir la relación de herencia entre clases, como la información de los distintos packages que componen las librerías base de Java. Es importante distinguir entre lo que significa herencia y package. Un package es una agrupación arbitraria de clases, una forma de organizar las clases. La herencia sin embargo consiste en crear nuevas clases en base a otras ya existentes. Las clases incluidas en un package no derivan en general de la misma clase. En la documentación on-line se presentan ambas visiones: “Package Index ” y “Class Hierarchy”. La primera presenta la estructura del API de Java agrupada por packages, mientras que en la segunda aparece la jerarquía de clases. Hay que resaltar el hecho de que todas las clases en Java son derivadas de la clase java.lang.Object, por lo que heredan todos los métodos y variables de ésta. Si se selecciona una clase en particular, la documentación muestra una descripción detallada de todos los métodos y variables de la clase. A su vez muestra su herencia completa (partiendo de la clase java.lang.Object). 3.4 Variables Dentro del Lenguaje Java Una variable en Java es un identificador que representa una palabra de memoria que contiene información. El tipo de información almacenado en una variable sólo puede ser del tipo con que se declaró esa variable. En Java hay dos tipos principales de variables: 80 CAPÍTULO 3. JAVA 1. Variables de tipos primitivos. Están definidas mediante un valor único y almacenan directamente ese valor siempre que pertenezca al rango de ese tipo. Por ejemplo una variable int almacena un valor entero como 1, 2, 0, -1, etc. Esto significa que al asignar una variable entera a otra variable entera, se copia el valor de la primera en el espacio que ocupa la segunda variable. 2. Variables referencia. Las variables referencia son referencias o nombres de una información más compleja: arrays u objetos de una determinada clase. Una referencia a un objeto es la dirección de un área en memoria destinada a representar ese objeto. El área de memoria se solicita con el operador new. Al asignar una variable de tipo referencia a objeto a otra variable se asigna la dirección y no el objeto referenciado por esa dirección. Esto significa que ambas variables quedan referenciando el mismo objeto. En Java una variable no puede almacenar directamente un objeto, como ocurre en C y C++. Por lo tanto cuando se dice en Java que una variable es un string, lo que se quiere decir en realidad es que la variable es una referencia a un string. Desde el punto de vista de su papel dentro del programa, las variables pueden ser: 1. Variables miembro de una clase: Se definen en una clase, fuera de cualquier método; pueden ser tipos primitivos o referencias. 2. Variables locales: Se definen dentro de un método o más en general dentro de cualquier bloque entre llaves {}. Se crean en el interior del bloque y se destruyen al finalizar dicho bloque. Pueden ser también tipos primitivos o referencias. En la Tabla 3.1 de la pág. 80 se muestra una declaración, el nombre de la variable introducida y el tipo de información que almacena la variable: Declaración int i; String s; int a []; int[]b; Identificador i s a b Tipo entero referencia a string referencia a arreglo de enteros referencia a arreglo de enteros Tabla 3.1: Tipos de Variables. En la Tabla 3.2 de la pág. 81 se muestran las dos grandes categorías de tipos para las variables en Java: En la Tabla 3.3de la pág. 81 se indica para cada tipo primitivo el número de bits que se emplea en su representación y el rango de valores que se puede almacenar en las variables de estos tipos. Se dice que un tipo A es de mayor rango que un tipo B si A es un superconjunto de B. Esto quiere decir que las variables de tipo B siempre se pueden asignar a variables de tipo A (eventualmente con pérdida de significancia). Por ejemplo int es de mayor rango que short, que a su vez es de mayor rango que byte. Float y double son de mayor rango que int. Double es de mayor rango que float. 3.4. VARIABLES DENTRO DEL LENGUAJE JAVA Tipos Primitivos int, short, byte, long char, boolean float, double 81 Referencias a Objetos Strings Arreglos otros objetos Tabla 3.2: Categorías de Variables. Tipo int short byte long boolean char float double Bits 32 16 8 64 1 16 32 64 Rango −231 ..231 − 1 −215 ..215 − 1 −27 ..27 − 1 −263 ..263 − 1 n/a n/a IEEE IEEE Ejemplos 0,1,5,-120,... 0,1,5,-120,... 0,1,5,-120,... 0,1,5,-120,... false, true ‘a’,‘A’,‘0’,‘*’,... 1.2 1.2 Tabla 3.3: Tipos Primitivos de Variables. Esto se puede quedar resumido de la siguiente manera: double > float > long > int > short > byte 3.4.1 Visibilidad y Vida de las Variables Se entiende por visibilidad, ámbito o scope de una variable, la parte de la aplicación donde dicha variable es accesible y por lo tanto puede ser utilizada en cualquier expresión. En Java todos las variables deben estar incluidas en una clase. En general las variables declaradas dentro de unas llaves {}, es decir dentro de un bloque, son visibles y existen dentro de estas llaves. Por ejemplo las variables declaradas al principio de una función existen mientras se ejecute la función; las variables declaradas dentro de un bloque if no serán válidas al finalizar las sentencias correspondientes a dicho if y las variables miembro de una clase (es decir declaradas entre las llaves {} de la clase pero fuera de cualquier método) son válidas mientras existe el objeto de la clase. Las variables miembro de una clase declaradas como public son accesibles a través de una referencia a un objeto de dicha clase utilizando el operador punto (.). Las variables miembro declaradas como private no son accesibles directamente desde otras clases. Las funciones miembro de una clase tienen acceso directo a todas las variables miembro de la clase sin necesidad de anteponer el nombre de un objeto de la clase. Sin embargo las funciones miembro de una clase B derivada de otra A, tienen acceso a todas las variables miembro de A declaradas como public o protected, pero no a las declaradas como private. Una clase derivada sólo puede acceder directamente a las variables y funciones miembro de su clase base declaradas como public o protected. Otra característica del lenguaje es que es posible declarar una variable dentro de un bloque con el mismo nombre que una 82 CAPÍTULO 3. JAVA variable miembro, pero no con el nombre de otra variable local. La variable declarada dentro del bloque oculta a la variable miembro en ese bloque. Para acceder a la variable miembro oculta será preciso utilizar el operador this. Uno de los aspectos más importantes en la programación orientada a objetos (OOP) es la forma en la cual son creados y eliminados los objetos. La forma de crear nuevos objetos es utilizar el operador new. Cuando se utiliza el operador new, la variable de tipo referencia guarda la posición de memoria donde está almacenado este nuevo objeto. Para cada objeto se lleva cuenta de por cuántas variables de tipo referencia es apuntado. La eliminación de los objetos la realiza el denominado garbage collector, quien automáticamente libera o borra la memoria ocupada por un objeto cuando no existe ninguna referencia apuntando a ese objeto. Lo anterior significa que aunque una variable de tipo referencia deje de existir, el objeto al cual apunta no es eliminado si hay otras referencias apuntando a ese mismo objeto. 3.5 Operadores en Java Java es un lenguaje rico en operadores, que son casi idénticos a los de C/C++. Estos operadores se describen brevemente a continuación. 3.5.1 Operadores Aritméticos Son operadores binarios (requieren siempre dos operandos) que realizan las operaciones aritméticas habituales: suma (+), resta (-), multiplicación (*), división (/) y resto de la división (%). 3.5.2 Operadores de Asignación Los operadores de asignación permiten asignar un valor a una variable. El operador de asignación por excelencia es el operador igual (=). La forma general de las sentencias de asignación con este operador es: variable = expression; Java dispone de otros operadores de asignación. Se trata de versiones abreviadas del operador (=) que realizan operaciones “acumulativas” sobre una variable. La siguiente Tabla 3.4 de la pág. 83, muestra estos operadores y su equivalencia con el uso del operador igual (=). 3.5.3 Operadores Unarios Los operadores más (+) y menos (-) unarios sirven para mantener o cambiar el signo de una variable, constante o expresión numérica. Su uso en Java es el estándar de estos operadores. 3.5. OPERADORES EN JAVA Operador += -= =* =/ %= Utilización op1 + = op2 op1 - = op2 op1 * = op2 op1 / = op2 op1% = op2 83 ExpresiónEquivalente op1 = op1 + op2 op1 = op1 - op2 op1 = op1 * op2 op1 = op1 / op2 op1 = op1 % op2 Tabla 3.4: Operadores de asignación. 3.5.4 Operadores Incrementales Java dispone del operador incremento (++) y decremento (—). El operador (++) incrementa en una unidad la variable a la que se aplica, mientras que (—) la reduce en una unidad. Estos operadores se pueden utilizar de dos formas: 1. Precediendo a la variable (por ejemplo: ++i). En este caso primero se incrementa la variable y luego se utiliza (ya incrementada) en la expresión en la que aparece. 2. Siguiendo a la variable (por ejemplo: i++). En este caso primero se utiliza la variable en la expresión (con el valor anterior) y luego se incrementa. En muchas ocasiones estos operadores se utilizan para incrementar una variable fuera de una expresión. En este caso ambos operadores son equivalente. Si se utilizan en una expresión más complicada, el resultado de utilizar estos operadores en una u otra de sus formas será diferente. La actualización de contadores en bucles for es una de las aplicaciones más frecuentes de estos operadores. 3.5.5 Operadores Relacionales Los operadores relacionales sirven para realizar comparaciones de igualdad, desigualdad y relación de menor o mayor. El resultado de estos operadores es siempre un valor boolean (true o false) según se cumpla o no la relación considerada. La siguiente Tabla 3.5 de la pág. 84 muestra los operadores relacionales de Java. Estos operadores se utilizan con mucha frecuencia en las bifurcaciones y en los bucles, que se verán luego. Ejemplo de Operadores Incrementales y Operadores Relacionales en un método. public void cambiarParesEntrenamiento(double[ ] paresEntrenamiento){ /* inicialización de sus valores a partir de los valores pasados como argumentos */ for(int i = 0; i< paresEntrenamiento.length; i++) {for(int j = 0; j< numeroNeuronasEntrada; j++) 84 CAPÍTULO 3. JAVA Operador > >= < <= == ! = Utilización op1 > op2 op1 >= op2 op1 < op2 op1 <= op2 op1 == op2 op1 != op2 El resultado es true si op1 es mayor que op2 si op1 es mayor o igual que op2 si op1 es menor que op 2 si op1 es menor o igual que op2 si op1 y op2 son iguales sio p1 y op2 son diferentes Tabla 3.5: Operadores relacionales. {entradaEntrenamiento[i][j] = paresEntrenamiento[i][j]; } for(int j = 0; j< numeroSalidas; j++) {salidaEntrenamiento[i][j] = paresEntrenamiento[i][j+numeroNeuronasEntrada]; } } } 3.5.6 Operador de Concatenación de Cadenas de Caracteres (+) El operador más (+) se utiliza también para concatenar cadenas de caracteres. Por ejemplo, para escribir una cantidad con un rótulo puede utilizarse la sentencia: editor.append(“Error Obtenido:” + String.valueOf(imprimoError) + “\n”); editor.append(“Iteraciones:”+ String.valueOf(imprimoIteraciones) + “\n”); editor.append(“Inicio: ” + horaInicial.toString() + “\n”); editor.append(“Final: ” + horaFinal.toString() + “\n”); donde el operador de concatenación se utiliza dos veces para construir la cadena de caracteres que se desea imprimir. Las variables imprimoErrror, imprimoIteraciones, horaInicial, horaFinal son convertidas en cadena de caracteres para poder concatenarlas. 3.5.7 Precedencia de Operadores El orden en que se realizan las operaciones es fundamental para determinar el resultado de una expresión. Por ejemplo, el resultado de x/y*z depende de qué operación (la división o el producto) se realice primero. La Tabla 3.6 de la pág. 85 muestra el orden en que se ejecutan los distintos operadores en una sentencia, de mayor a menor precedencia: 3.6. ESTRUCTURAS DE PROGRAMACIÓN Nombre Postfijos Unarios De creación Multiplicativo Adición Shift Relacional Igualdad AND Or Excluyente Or Incluyente Logico AND Logico OR Condicional Asignación 85 Sintáxis [ ] .(params) expr++ expr++expr —expr +expr -expr ! (type) expr */% +<< >> >>> <> <= >= instanceof == ! = & ^ | && || ?: = += -= *= /= %= &= ^= |= <<= >>= >>>= Tabla 3.6: Precedencia de Operadores. En Java, todos los operadores binarios, excepto los operadores de asignación, se evalúan de izquierda a derecha. Los operadores de asignación se evalúan de derecha a izquierda, lo que significa que el valor de la izquierda se copia sobre la variable de la derecha. 3.6 Estructuras de Programación Las estructuras de programación o estructuras de control permiten tomar decisiones y realizar un proceso repetidas veces. Son los denominados bifurcaciones y bucles. En la mayoría de los lenguajes de programación, este tipo de estructuras son comunes en cuanto a concepto, aunque su sintaxis varía de un lenguaje a otro. La sintaxis de Java coincide prácticamente con la utilizada en C/C++, lo que hace que para un programador de C/C++ no suponga ninguna dificultad adicional. 3.6.1 Sentencias o Expresiones Una expresión es un conjunto variables unidos por operadores. Son órdenes que se le dan al computador para que realice una tarea determinada. Una sentencia es una expresión que acaba en punto y coma (;). Se permite incluir varias sentencias en una línea, aunque lo habitual es utilizar una línea para cada sentencia. A continuación se muestra un ejemplo de una línea compuesta de tres sentencias: i = 0; j = 5; x = i + j; 86 3.6.2 CAPÍTULO 3. JAVA Comentarios Existen dos formas diferentes de introducir comentarios entre el código de Java (en realidad son tres, como pronto se verá). Son similares a la forma de realizar comentarios en el lenguaje C/C++. Los comentarios son tremendamente útiles para poder entender el código utilizado, facilitando de ese modo futuras revisiones y correcciones. Además permite que cualquier persona distinta al programador original pueda comprender el código escrito de una forma más rápida. Se recomienda acostumbrarse a comentar el código desarrollado. De esta forma se simplifica también la tarea de estudio y revisión posteriores. Java interpreta que todo lo que aparece a la derecha de dos barras “// ” en una línea cualquiera del código es un comentario del programador y no lo tiene en cuenta. El comentario puede empezar al comienzo de la línea o a continuación de una instrucción que debe ser ejecutada. La segunda forma de incluir comentarios consiste en escribir el texto entre los símbolos “ /* */ ”. Este segundo método es válido para comentar más de una línea de código. Por ejemplo: // Esta línea es un comentario int a=1; // Comentario a la derecha de una sentencia // Esta es la forma de comentar más de una línea utilizando // las dos barras. Requiere incluir dos barras al comienzo de cada línea /* Esta segunda forma es mucho más cómoda para comentar un número elevado de líneas ya que sólo requiere modificar el comienzo y el final. */ En Java existe además una forma especial de introducir los comentarios (utilizando /***/ más algunos caracteres especiales) que permite generar automáticamente la documentación sobre las clases y packages desarrollados por el programador. Una vez introducidos los comentarios, el programa javadoc.exe (incluido en el JDK) genera de forma automática la información de forma similar a la presentada en la propia documentación del JDK. La sintaxis de estos comentarios y la forma de utilizar el programa javadoc.exe se puede encontrar en la información que viene con el JDK. 3.6.3 Bifurcaciones Las bifurcaciones permiten ejecutar una de entre varias acciones en función del valor de una expresión lógica o relacional. Se tratan de estructuras muy importantes ya que son las encargadas de controlar el flujo de ejecución de un programa. Se exponen dos variantes del de tipo if. Bifurcación if Esta estructura permite ejecutar un conjunto de sentencias en función del valor que tenga la expresión de comparación. Ejemplo: se ejecuta si la expresión de comparación (error < errorMinimo) tiene valor true: protected void comprobarNuevoMinimo() { 3.6. ESTRUCTURAS DE PROGRAMACIÓN 87 if (error < errorMinimo) {errorMinimo = error; vectorDisMinimo = (double[ ])(vectorDis.clone()); } /* fin del if */ } Las llaves {} sirven para agrupar en un bloque las sentencias que se han de ejecutar, y no son necesarias si sólo hay una sentencia dentro del if. Bifurcación if else Análoga a la anterior, de la cual es una ampliación. Las sentencias incluidas en el else se ejecutan en el caso de no cumplirse la expresión de comparación (false), Ejemplo: public double decirSalidaActual(int indiceEtapa) { if(pila != null) {return pila[indiceEtapa];} else {System.out.println(“Fallo: Pila no creada”); return 0; } } 3.6.4 Bucles Un bucle se utiliza para realizar un proceso repetidas veces. Se denomina también lazo o loop. El código incluido entre las llaves {} (opcionales si el proceso repetitivo consta de una sola línea), se ejecutará mientras se cumpla unas determinadas condiciones. Hay que prestar especial atención a los bucles infinitos, hecho que ocurre cuando la condición de finalizar el bucle (booleanExpression) no se llega a cumplir nunca. Se trata de un fallo muy típico, habitual sobre todo entre programadores poco experimentados. Bucle while En el siguiente ejemplo se muestra que se ejecutará la sentencia fin++ mientras la expresión (capas.charAt(fin)!=‘,’ && capas.charAt(fin)!=-1) sea verdadera. for (int j=0; j < numeroCapas; j++) {int fin = principio; try { while (capas.charAt(fin) != ‘,’ && capas.charAt(fin) != -1) 88 CAPÍTULO 3. JAVA {fin++; } } } Bucle for A continuación se podrá apreciar la utilización del bucle for: /* calcular el nuevo vector de diseño */ for (int i = 0; i < vectorDis.length; i++) {vectorDis[i] = vectorDis[i] + learningRate * S[i]; } La sentencia int i = 0 (inicialización) se ejecuta al comienzo del for, e i++ (incremento) después de vectorDis[i] = vectorDis[i] + learningRate * S[i] (sentencia). La expresión booleana (vectorDis.length) se evalúa al comienzo de cada iteración; el bucle termina cuando la expresión de comparación toma el valor false. Bucle do while Es similar al bucle while pero con la particularidad de que el control está al final del bucle (lo que hace que el bucle se ejecute al menos una vez, independientemente de que la condición se cumpla o no). Una vez ejecutados las sentencias, se evalúa la condición: si resulta true se vuelven a ejecutar las sentencias incluidas en el bucle, mientras que si la condición se evalúa a false finaliza el bucle. do{ /* calcular el gradiente del vector fijar el vector de diseño */ problema.fijoVector(vectorDis); /* incrementar el contador de iteraciones*/ step++; } while (error > errorDeseado && step < iteracionesMaximas); /* ... hasta que el error sea menor o igual que el deseado o */ /* se alcance el número de iteraciones pasado como argumento */ problema.fijoVector(vectorDis); 3.7. CLASES EN JAVA 89 Sentencia return Una forma de salir de un bucle es utilizar la sentencia return. Esta sentencia sale también de un método o de una función. En el caso de que la función devuelva alguna variable, este valor se deberá poner a continuación del return. public double devuelveErrorMinimo() {return errorMinimo; } Bloque try{...} catch{...} finally{...} Java incorpora en el propio lenguaje la gestión de errores. El mejor momento para detectar los errores es durante la compilación. Sin embargo prácticamente sólo los errores de sintaxis son detectados en esta operación. El resto de problemas surgen durante la ejecución de los programas. En el lenguaje Java, una Exception es un cierto tipo de error o una condición anormal que se ha producido durante la ejecución de un programa. Algunas excepciones son fatales y provocan que se deba finalizar la ejecución del programa. En este caso conviene terminar ordenadamente y dar un mensaje explicando el tipo de error que se ha producido. Otras excepciones, como por ejemplo no encontrar un fichero en el que hay que leer o escribir algo, pueden ser recuperables. En este caso el programa debe dar al usuario la oportunidad de corregir el error (dando por ejemplo un nuevo path del fichero no encontrado). Los errores se representan mediante clases derivadas de la clase Throwable, pero los que tiene que chequear un programador derivan de Exception (java.lang.Exception que a su vez deriva de Throwable). Existen algunos tipos de excepciones que Java obliga a tener en cuenta. Esto se hace mediante el uso de bloques try, catch y finally. El código dentro del bloque try está “vigilado”: Si se produce una situación anormal y se lanza como consecuencia una excepción, el control pasa al bloque catch que se hace cargo de la situación y decide lo que hay que hacer. Se pueden incluir tantos bloques catch como se desee, cada uno de los cuales tratará un tipo de excepción. Finalmente, si está presente, se ejecuta el bloque finally, que es opcional, pero que en caso de existir se ejecuta siempre, sea cual sea el tipo de error. En el caso en que el código de un método pueda generar una Exception y no se desee incluir en dicho método la gestión del error (es decir los bucles try/catch correspondientes), es necesario que el método pase la Exception al método desde el que ha sido llamado. Esto se consigue mediante la adición de la palabra throws seguida del nombre de la Exception concreta, después de la lista de argumentos del método. A su vez el método superior deberá incluir los bloques try/catch o volver a pasar la Exception. De esta forma se puede ir pasando la Exception de un método a otro hasta llegar al último método del programa, el método main(). 3.7 Clases en Java Las clases son el centro de la Programación Orientada a Objetos (OOP - Object Oriented Programming). Algunos conceptos importantes de la POO son los siguientes: 90 CAPÍTULO 3. JAVA 1. Encapsulación: Las clases pueden ser declaradas como públicas (public) y como package (accesibles sólo para otras clases del package). Las variables miembro y los métodos pueden ser public, private, protected y package. De esta forma se puede controlar el acceso y evitar un uso inadecuado. 2. Herencia: Una clase puede derivar de otra (extends), y en ese caso hereda todas sus variables y métodos. Una clase derivada puede añadir nuevas variables y métodos y/o redefinir las variables y métodos heredados. 3. Polimorfismo: Los objetos de distintas clases pertenecientes a una misma jerarquía o que implementan una misma interface pueden tratarse de una forma general e individualizada, al mismo tiempo. Esto facilita la programación y el mantenimiento del código. 3.7.1 Características Importantes de las Clases A continuación se enumeran algunas características importantes de las clases: 1. Todas las variables y funciones de Java deben pertenecer a una clase. No hay variables y funciones globales. 2. Si una clase deriva de otra (extends), hereda todas sus variables y métodos. 3. Java tiene una jerarquía de clases estándar de la que pueden derivar las clases que crean los usuarios. 4. Una clase sólo puede heredar de una única clase (en Java no hay herencia múltiple). Si al definir una clase no se especifica de qué clase deriva, por defecto la clase deriva de Object. La clase Object es la base de toda la jerarquía de clases de Java. 5. En un fichero se pueden definir varias clases, pero en un fichero no puede haber más que una clase public. Este fichero se debe llamar como la clase public que contiene con extensión *.java. Con algunas excepciones, lo habitual es escribir una sola clase por fichero. 6. Si una clase contenida en un fichero no es public, no es necesario que el fichero se llame como la clase. 7. Los métodos de una clase pueden referirse de modo global al objeto de esa clase al que se aplican por medio de la referencia this. 8. Las clases se pueden agrupar en packages, introduciendo una línea al comienzo del fichero (package packageName;). Esta agrupación en packages está relacionada con la jerarquía de directorios y ficheros en la que se guardan las clases. 3.7.2 Métodos o Funciones Miembros Métodos de Objeto Los métodos son funciones definidas dentro de una clase. Salvo los métodos static o de clase, se aplican siempre a un objeto de la clase por medio del operador punto (.). Dicho 3.7. CLASES EN JAVA 91 objeto es su argumento implícito. Los métodos pueden además tener otros argumentos explícitos que van entre paréntesis, a continuación del nombre del método. La primera línea de la definición de un método se llama declaración o header; el código comprendido entre las llaves {} es el cuerpo o body del método. Considérese el siguiente ejemplo: imprimoError=algor.devuelveErrorMinimo(); public double devuelveErrorMinimo() {return errorMinimo; } La Clase Object Como ya se ha dicho, la clase Object es la raíz de toda la jerarquía de clases de Java. Todas las clases de Java derivan de Object. La clase Object tiene métodos interesantes para cualquier objeto que son heredados por cualquier clase. Entre ellos se pueden citar los siguientes: 1. Métodos que pueden ser redefinidos por el programador: • clone(): Crea un objeto a partir de otro objeto de la misma clase. El método original heredado de Object lanza una CloneNotSupportedException. Si se desea poder clonar una clase hay que implementar la interface Cloneable y redefinir el método clone(). Este método debe hacer una copia miembro a miembro del objeto original. No debería llamar al operador new ni a los constructores. • equals(): Indica si dos objetos son o no iguales. Devuelve true si son iguales, tanto si son referencias al mismo objeto como si son objetos distintos con iguales valores de las variables miembro. • toString(): Devuelve un String que contiene una representación del objeto como cadena de caracteres, por ejemplo para imprimirlo o exportarlo. • finalize(): Este método ya se ha visto al hablar de los finalizadores. 2. Métodos que no pueden ser redefinidos (son métodos final): • getClass(): Devuelve un objeto de la clase Class, al cual se le pueden aplicar métodos para determinar el nombre de la clase, su super-clase, las interfaces implementadas, etc. Se puede crear un objeto de la misma clase que otro sin saber de qué clase es. • notify(), notifyAll() y wait(): Son métodos relacionados con los threads (hilos). 92 CAPÍTULO 3. JAVA 3.8 3.8.1 Algunas Clases de Utilidad Clase Arrays Los arrays de Java (vectores, matrices, hiper-matrices de más de dos dimensiones) se tratan como objetos de una clase predefinida. Los arrays son objetos, pero con algunas características propias. Los arrays pueden ser asignados a objetos de la clase Object y los métodos de Object pueden ser utilizados con arrays. Algunas de sus características más importantes de los arrays son las siguientes: 1. Los arrays se crean con el operador new seguido del tipo y número de elementos. 2. Se puede acceder al número de elementos de un array con la variable miembro implícita length (por ejemplo, vect.length). 3. Se accede a los elementos de un array con los corchetes [ ] y un índice que varía de 0 a length-1. 4. Se pueden crear arrays de objetos de cualquier tipo. En principio un array de objetos es un array de referencias que hay que completar llamando al operador new. 5. Los elementos de un array se inicializan al valor por defecto del tipo correspondiente (cero para valores numéricos, la cadena vacía para Strings, false para boolean, null para referencias). 6. Como todos los objetos, los arrays se pasan como argumentos a los métodos por referencia. 7. Se pueden crear arrays anónimos (por ejemplo, crear un nuevo array como argumento actual en la llamada a un método). Inicialización de Arrays Los arrays se pueden inicializar con valores entre llaves {...} separados por comas. También los arrays de objetos se pueden inicializar con varias llamadas a new dentro de unas llaves {...}. Si se igualan dos referencias a un array no se copia el array, sino que se tiene un array con dos nombres, apuntando al mismo y único objeto. Ejemplo de creación de una referencia a un array: /*vector de pesos */ public double[ ] pesos; También existen arrays bidimensionales, que se crean de un modo muy similar al de C++ (con reserva dinámica de memoria). En Java una matriz es un vector de vectores fila, o más en concreto un vector de referencias a los vectores fila. Con este esquema, cada fila podría tener un número de elementos diferente. Una matriz se puede crear directamente en la siguiente forma: 3.8. ALGUNAS CLASES DE UTILIDAD 93 /*vector de las entradas de los pares de entrenamiento*/ protected double[ ][ ] entradaEntrenamiento; 3.8.2 Clases String y StringBuffer Las clases String y StringBuffer están orientadas a manejar cadenas de caracteres. La clase String está orientada a manejar cadenas de caracteres constantes, es decir, que no pueden cambiar. La clase StringBuffer permite que el programador cambie la cadena insertando, borrando, etc. La primera es más eficiente, mientras que la segunda permite más posibilidades. Ambas clases pertenecen al package java.lang, y por lo tanto no hay que importarlas. Hay que indicar que el operador de concatenación (+) entre objetos de tipo String utiliza internamente objetos de la clase StringBuffer y el método append(). Los métodos de String se pueden utilizar directamente sobre literals (cadenas entre comillas), como por ejemplo: “Hola”.length(). Métodos de la Clase String Algunos métodos de String y la función que realizan: • String(...): Constructores para crear Strings a partir de arrays de bytes o de caracteres. • String(String str) yString(StringBuffer sb): Costructores a partir de un objeto String o StringBuffer. • charAt(int): Devuelve el carácter en la posición especificada. • getChars(int, int, char[ ], int): Copia los caracteres indicados en la posición indicada de un array de caracteres. • length(): Devuelve el número de caracteres de la cadena. • toLowerCase(): Convierte en minúsculas (puede tener en cuenta el locale). • toUpperCase(): Convierte en mayúsculas (puede tener en cuenta el locale). • valueOf(): Devuelve la representación como String de sus argumento. Admite Object, arrays de caracteres y los tipos primitivos. 3.8.3 Clase Double La clase java.lang.Double deriva de Number, que a su vez deriva de Object. Esta clase contiene un valor primitivo de tipo double. 94 CAPÍTULO 3. JAVA Algunos Métodos de la Clase Double • Double(double) y Double(String): Los constructores de esta clase. • doubleValue(), floatValue(), longValue(), intValue(), shortValue(), byteValue(): Métodos para obtener el valor del tipo primitivo. • String toString(), Double valueOf(String): Conversores con la clase String. • isInfinite(), isNaN(): Métodos de chequear condiciones. • equals(Object): Compara con otro objeto. 3.8.4 Clase Integer La clase java.lang.Integer tiene como variable miembro un valor de tipo int. Algunos Métodos de la Clase Integer • Integer(int) y Integer(String): Constructores de la clase. • doubleValue(), floatValue(), longValue(),intValue(), shortValue(), byteValue(): Conversores con otros tipos primitivos. • Integer decode(String), Integer parseInt(String), String toString(), Integer ValueOf(String): Conversores con String del sistema a partir del nombre de dicha propiedad. 3.9 3.9.1 El AWT (Abstract Windows Toolkit) Qué es el AWT El AWT (Abstract Windows Toolkit) es la parte de Java que se ocupa de construir interfaces gráficas de usuario. Aunque el AWT ha estado presente en Java desde la versión 1.0, la versión 1.1 representó un cambio notable, sobre todo en lo que respecta al modelo de eventos. La versión 1.2 ha incorporado un modelo distinto de componentes llamado Swing, que también está disponible en la versión 1.1 como package adicional. 3.9.2 Creación de una Interface Gráfica de Usuario Para construir una interface gráfica de usuario hace falta: 1. Un “contenedor” o container, que es la ventana o parte de la ventana donde se situarán los componentes (botones, barras de desplazamiento, etc.) y donde se realizarán los dibujos. Se correspondería con un formulario o una picture box de Visual Basic. 2. Los componentes: menúes, botones de comando, barras de desplazamiento, cajas y áreas de texto, botones de opción y selección, etc. Se corresponderían con los controles de Visual Basic. 3.9. EL AWT (ABSTRACT WINDOWS TOOLKIT) 95 3. El modelo de eventos. El usuario controla la aplicación actuando sobre los componentes, de ordinario con el ratón o con el teclado. Cada vez que el usuario realiza una determinada acción, se produce el evento correspondiente, que el sistema operativo transmite al AWT. El AWT crea un objeto de una determinada clase de evento, derivada de AWTEvent. Este evento es transmitido a un determinado método para que lo gestione. En Visual Basic el entorno de desarrollo crea automáticamente el procedimiento que va a gestionar el evento (uniendo el nombre del control con el tipo del evento mediante el carácter _ ) y el usuario no tiene más que introducir el código. En Java esto es un poco más complicado: el componente u objeto que recibe el evento debe “registrar” o indicar previamente qué objeto se va a hacer cargo de gestionar ese evento. 3.9.3 Objetos “event source” y Objetos “event listener” El modelo de eventos de Java está basado en que los objetos sobre los que se producen los eventos (event sources) “registran” los objetos que habrán de gestionarlos (event listeners), para lo cual los event listeners habrán de disponer de los métodos adecuados. Estos métodos se llamarán automáticamente cuando se produzca el evento. La forma de garantizar que los event listeners disponen de los métodos apropiados para gestionar los eventos es obligarles a implementar una determinada interface Listener. Las interfaces Listener se corresponden con los tipos de eventos que se pueden producir. Las capacidades gráficas del AWT resultan pobres y complicadas en comparación con lo que se puede conseguir con Visual Basic, pero tienen la ventaja de poder ser ejecutadas casi en cualquier ordenador y con cualquier sistema operativo. 3.9.4 Proceso a Seguir Para Crear Una Aplicación Interactiva (Orientada a Eventos) Pasos que se pueden seguir para construir una aplicación orientada a eventos sencilla, con interface gráfica de usuario: 1. Determinar los componentes que van a constituir la interface de usuario (botones, cajas de texto, menúes, etc.). 2. Crear una clase para la aplicación que contenga la función main(). 3. Crear una clase Ventana, sub-clase de Frame, que responda al evento WindowClosing(). 4. La función main() deberá crear un objeto de la clase Ventana (en el que se van a introducir las componentes seleccionadas) y mostrarla por pantalla con el tamaño y posición adecuados. 5. Añadir al objeto Ventana todos los componentes y menúes que deba contener. 6. Definir los objetos Listener (objetos que se ocuparán de responder a los eventos, cuyas clases implementan las distintas interfaces Listener) para cada uno de los eventos que deban estar soportados. En aplicaciones pequeñas, el propio objeto Ventana se 96 CAPÍTULO 3. JAVA puede ocupar de responder a los eventos de sus componentes. En programas más grandes se puede crear uno o más objetos de clases especiales para ocuparse de los eventos. 7. Finalmente, se deben implementar los métodos de las interfaces Listener que se vayan a hacer cargo de la gestión de los eventos. En la aplicación se podrá observar la gran variedad de componentes de AWT que se utilizaron. También se acudió a los paquetes de Swing , por ejemplo para la implementación de un hilo en la presentación de la aplicación. El objetivo de este capítulo ha sido brindar nociones leves sobre este lenguaje de programación, mostrando algunos ejemplos que se pueden encontrar en el código fuente de la aplicación. 3.10 Errores más Frecuentes en la Programación con Java A continuación se presenta una varios ejemplos de errores, vistos desde el punto de vista de la portabilidad, porque quizá el sine qua non de Java, en última instancia sea perseguir una verdadera independencia de plataforma. Los errores no tienen ningún orden de dificultad, no son más que algunos de ellos en los que puede caer cualquier programador. Hay muchísimas formas cometer fallos a la hora de programar en Java; algunas se deben simplemente a malos hábitos y son muy difíciles de encontrar, mientras que otros saltan a la vista al instante. Los errores de programación más obvios, también son los que con más frecuencia cometen los programadores. Quizás muchos de los fallos se evitarían si los programadores intentarán aplicar calidad a sus programas desde el momento mismo de concebir el programa, y no la tendencia de aplicar pureza a la aplicación en el último momento. 3.10.1 Scheduling de Hilos de Ejecución El scheduling de los hilos de ejecución, es decir, el tiempo que el sistema destina a la ejecución de cada uno de los hilos de ejecución, puede ser distinto en diferentes plataformas. Si no se tienen en cuenta las prioridades o se deja al azar la prevención de que dos hilos de ejecución accedan a un mismo objeto al mismo tiempo, el programa no será portable. El siguiente programa, por ejemplo, no es portable: class Contador implements Runnable { static long valor = 0; public void run() { valor += 1; } public static void main( String args[] ) { 3.10. ERRORES FRECUENTES DE PROGRAMACIÓN 97 try { Thread hilo1 = new Thread( new Contador() ); hilo1.setPriority( 1 ); Thread hilo2 = new Thread( new Contador() ); hilo2.setPriority( 2 ); hilo1.start(); hilo2.start(); hilo1.join(); hilo2.join(); Systtem.out.println( valor ); } catch( Exception e ) { e.printStackTrace(); } } } Este programa puede no imprimir “2” en todas las plataformas, porque los dos hilos de ejecución no están sincronizados y, desgraciadamente, este es un problema muy profundo y no hay forma de detectar su presencia ni adivinar el momento en que va a ocurrir. Una solución simple, y drástica, es hacer todos los métodos sincronizados. Pero esto también tiene problemas porque puede presentar como puntos sin retorno obvios, lo que en realidad es una corrupción de datos. El scheduling de los hilos de ejecución es uno de los aspectos más problemáticos de la programación Java, porque la naturaleza del problema se vuelve global, al intervenir varios hilos de ejecución. No se puede buscar el problema en una parte del programa, es imprescindible entender y tratar el programa en su globalidad. Además, hay ejemplos de contención de hilos que no serán detectados. Por ejemplo, en la clase Contador anterior no se detectará el problema ya que la contención está en el acceso al campo, en lugar de en el acceso al método. 3.10.2 Errores en el Uso de las Características de Portabilidad de Java Hay características de portabilidad en el API de Java. Es posible, pero menos portable, escribir código que no haga uso de estas características. Muchas de las propiedades del sistema proporcionan información sobre la portabilidad; por ejemplo, se pueden utilizar las propiedades del sistema para conocer cuál es el carácter definido como fin de línea o el que se emplea como terminador del archivo, para emplear el adecuado a la plataforma en que se está ejecutando el programa. Java proporciona dos métodos para facilitar la escritura de programas portables en este sentido. Por un lado, utilizar el método println() en vez de imprimir las cadenas seguidas del terminador de cadena embebido; o también, utilizar la expresión System.getProperty(“line.separator”) para conocer cuál es el terminado de línea que se utiliza en la plataforma en que se está ejecutando el programa. 98 CAPÍTULO 3. JAVA En general, el uso de las propiedades facilita en gran modo la portabilidad y debería extenderse su uso siempre que fuese aplicable. 3.10.3 Uso de Directorios Definidos Un error muy común y fácil de cometer entre los programadores, aunque igual de fácil de corregir es la designación en el código de nombre de los archivos, que pueden dar lugar a problemas de portabilidad, pero cuando se añade el directorio en que se sitúan, seguro que estos problemas aparecerán. Estos fallos son más comunes entre programadores con viejos hábitos, que eran dependientes del sistema operativo, y que son difíciles de olvidar. La forma más portable de construir un File para un fichero en un directorio es utilizar el constructor File(File,String). Otra forma sería utilizar las propiedades para conocer cuál es el separador de ficheros y el directorio inicial; o también, preguntarle al operador a través de una caja de diálogo. Otro problema es la noción de camino absoluto, que es dependiente del sistema. En Unix los caminos absolutos empiezan por /, mientras que en Windows pueden empezar por cualquier letra. Por esta razón, el uso de caminos absolutos que no sean dependientes de una entrada por operador o de la consulta de las propiedades del sistema no será portable. El ejemplo siguiente proporciona una clase útil para la construcción de nombres de archivos. La última versión del JDK es mucho más exhaustiva, y detecta más fácilmente los errores cometidos en los directorios y nombres de ficheros. import java.io.File; import java.util.StringTokenizer; public class UtilFichero { /* Crea un nuevo fichero con el nombre de otros. Si la base inicial es * nula, parte del directorio actual */ public static File dirInicial( File base,String path[] ) { File valor = base; int i=0; if( valor == null && path.length == 0 ) { valor = new File( path[i++] ); } for( ; i < path.length; i++ ) { valor = new File( valor,path[i] ); } return( valor ); } public static File desdeOrigen( String path[] ) { 3.10. ERRORES FRECUENTES DE PROGRAMACIÓN return( dirInicial( null,path ) ); } public static File desdeProp( String nombrePropiedad ) { String pd = System.getProperty( nombrePropiedad ); return( new File( pd ) ); } // Utilizando la propiedad del sistema “user.dir” public static File userDir() { return( desdeProp( “user.dir” ) ); } // Utilizando la propiedad del sistema “java.home” public static File javaHome() { return( desdeProp( “java.home” ) ); } // Utilizando la propiedad del sistema “user.home” public static File userHome() { return( desdeProp( “user.home” ) ); } /* Separa el primer argumento, utilizando el segundo argumetno como * carácter separador. * Es muy útil a la hora de crear caminos de ficheros portables */ public static String[] split( String p,String sep ) { StringTokenizer st = new StringTokenizer( p,sep ); String valor[] = new String[st.countTokens()]; for( int i=0; i < valor.length; i++ ) { valor[i] = st.nextToken(); } return( valor ); } } 99 100 3.10.4 CAPÍTULO 3. JAVA Carga de Drivers JDBC El interfaz JDBC, definido por el paquete java.sql, proporciona gran flexibilidad a la hora de codificar la carga del driver JDBC a utilizar. Esta flexibilidad permite la sustitución de diferentes drivers sin que haya que modificar el código, a través de la clase DriverManager, que selecciona entre los drivers disponibles en el momento de establecer la conexión. Los drivers se pueden poner a disposición de DriverManager a través de la propiedad del sistema jdbc.drivers o cargándolos explícitamente usando el método java.lang.Class.forName(). También es posible la carga de una selección de drivers, dejando que el mecanismo de selección de DriverManager encuentre el adecuado en el momento de establecer la conexión con la base de datos. Hay que tener siempre en cuenta los siguientes puntos: • La prueba de drivers se intenta siempre en el orden en que se han registrado, por lo que los primeros drivers tienen prioridad sobre los últimos cargados, con la máxima prioridad para los drivers listados en jdbc.drivers. • Un driver que incluya código nativo fallará al cargarlo sobre cualquier plataforma diferente de la que fue diseñado; por lo que el programa deberá recoger la excepción ClassNotFoundException. • Un driver con código nativo no debe registrarse con DriverManager hasta que no se sepa que la carga ha tenido éxito. • Un driver con código nativo no está protegido por la caja negra de Java, así que puede presentar potenciales problemas de seguridad. 3.10.5 Terminación de Líneas Las distintas plataformas de sistemas operativos tienen distintas convenciones para la terminación de líneas en un fichero de texto. Por esto debería utilizarse el método println(), o la propiedad del sistema line.separator, para la salida; y para la entrada utilizar los métodos readLine(). Java internamente utiliza Unicode, que al ser un estándar internacional, soluciona el problema a la hora de codificar; pero el problema persiste al leer o escribir texto en un archivo. En el JDK 1.1 se utilizan las clases java.io.Reader y java.io.Writer para manejar la conversión del set de caracteres, pero el problema puede surgir cuando se leen o escriben archivos ASCII planos, porque en el ASCII estándar no hay un carácter específico para la terminación de líneas; algunas máquinas utilizan \n, otras usan \r, y otras emplean la secuencia \r\n. Enarbolando la bandera de la portabilidad, deberían utilizarse los métodos println() para escribir una línea de texto, o colocar un marcador de fin de línea. También, usar el método readLine() de la clase java.io.BufferedReader para recoger una línea completa de texto. Los otros métodos readLine() son igualmente útiles, pero el de la clase BufferedReader proporciona al código también la traslación. 3.11. APPLETS 3.10.6 101 Entrada/Salida por Archivo Las clases de entrada y salida del JDK 1.0 no son portables a plataformas que no soporten formatos nativos de archivos no-ASCII. Es fácil para el programador suponer alegremente que todo el mundo es ASCII. Pero la realidad no es esa, los chinos y los japoneses, por ejemplo, no puedes escribir nada con los caracteres ASCII. Hay que tener esto en cuenta si se quiere que los programas viajen fuera del país propio. 3.10.7 Fuentes de Caracteres El tamaño y disponibilidad de varios tipos de fuentes varía de pantalla a pantalla, incluso en una misma plataforma hardware, dependiendo de la instalación que se haya hecho. Esto es algo que no descalifica totalmente el programa, porque se verá defectuosamente, pero el programa podrá seguir usándose; pero debería prevenirse, porque se presupone que el programador desea que su software aparezca de la mejor manera posible en cualquier plataforma. El modo mejor de evitar todo esto es no codificar directamente el tamaño de los textos, dejar que los textos asuman su tamaño en relación al layout, y utilizar los métodos de la clase FontMetrics para encontrar el tamaño en que aparecen los caracteres de una cadena sobre un Canvas. Cuando se coloca una fuente que no se encuentra entre las de defecto, hay que asegurarse siempre de colocar alguna de respaldo en el bloque catch. Cuando se crea un menú para seleccionar fuentes de caracteres, se debería utilizar el método java.awt.Toolkit.getFontList(), en lugar de especificar una lista de fuentes. Cuando se actualice un programa del JDK 1.0 al JDK 1.1, hay que tener en cuenta que los nombre de las fuentes de caracteres se han actualizado, tal como se indica en la documentación del método getFontList(). 3.11 3.12 APPLETS QUÉ ES UN APPLET Un applet es una mini-aplicación, escrita en Java, que se ejecuta en un browser (NetscapeNavigator, Microsoft Internet Explorer, ) al cargar una página HTML que incluye información sobre el applet a ejecutar por medio de las tags <APPLET>... </APPLET>. A continuación se detallan algunas características de las applets: 1. Los ficheros de Java compilados (*.class) se descargan a través de la red desde un servidor de Web o servidor HTTP hasta el browser en cuya Java Virtual Machine se ejecutan. Pueden incluir también ficheros de imágenes y sonido. 2. Las applets no tienen ventana propia: se ejecutan en la ventana del browser (en un panel). 3. Por la propia naturaleza abierta de Internet, las applets tienen importantes restricciones de seguridad, que se comprueban al llegar al browser: sólo pueden leer y escribir ficheros en el servidor del que han venido, sólo pueden acceder a una limitada información sobre el ordenador 102 CAPÍTULO 3. JAVA Figura 3.1: Jerarquia de Clases de Applets en el que se están ejecutando, etc. Con ciertas condiciones, las applets de confianza (trusted applets) pueden pasar por encima de estas restricciones. Aunque su entorno de ejecución es un browser, las applets se pueden probar sin necesidad de browser con la aplicación appletviewer del JDK de Sun. 3.12.1 Algunas características de las applets Las características de las applets se pueden considerar desde el puntode vista del programador y desde el del usuario. En este manual lo más importante es el punto de vista del programador: • Las applets no tienen un método main() con el que comience la ejecución. El papel central de su ejecución lo asumen otros métodos que se verán posteriormente. • Todas las applets derivan de la clase java.applet.Applet. LaFigura 3.1 de la pag.102 muestra la jerarquía de clases de la que deriva laclase Applet. Las applets deben redefinir ciertos métodosheredados de Applet que controlan su ejecución: init(),start(), stop(), destroy(). • Se heredan otros muchos métodos de las super-clases de Applet que tienen que ver con la generación de interfaces gráficas de usuario (AWT). Así, los métodos gráficos se heredan de Component, mientras que la capacidad de añadir componentes de interface de usuario se hereda de Container y de Panel. • Las applets también suelen redefinir ciertos métodos gráficos: los más importantes son paint() y update(), heredados de Component y de Container; y repaint() heredado de Component. 3.12. QUÉ ES UN APPLET 103 • Las applets disponen de métodos relacionados con la obtención de información, como por ejemplo: getAppletInfo(), getAppletContext(), getParameterInfo(), getParameter(), getCodeBase(), getDocumentBase(), e isActive(). El método showStatus() se utiliza para mostrar información en la barra de estado del browser.Existen otros métodos relacionados con imágenes y sonido: getImage(), getAudioClip(), play(), etc. 3.12.2 Métodos que controlan la ejecución de un applet Los métodos que se estudian en este Apartado controlan la ejecución de las applets. De ordinario el programador tiene que redefinir uno o más de estos métodos, pero no tiene que preocuparse de llamarlos: el browser se encarga de hacerlo. Método init() Se llama automáticamente al método init() en cuanto el browser o visualizador carga el applet. Este método se ocupa de todas las tareas de inicialización, realizando las funciones del constructor (al que el browser no llama). En Netscape Navigator se puede reinicializar un applet con Shift+Reload. Método start() El método start() se llama automáticamente en cuanto el applet se hace visible, después de haber sido inicializada. Se llama también cada vez que el applet se hace de nuevo visible después de haber estado oculta (por dejar de estar activa esa página del browser, al cambiar el tamaño de la ventana del browser, al hacer reload, etc.). Es habitual crear threads en este método para aquellas tareas que, por el tiempo que requieren, dejarían sin recursos al applet o incluso al browser. Las animaciones y ciertas tareas a través de Internet son ejemplos de este tipo de tareas. Método stop() El método stop() se llama de forma automática al ocultar el applet (por haber haber dejado de estar activa la página del browser, por hacer reload o resize, etc.). Con objeto de no consumir recursos inútilmente, en este método se suelen parar las threads que estén corriendo en el applet, por ejemplo para mostrar animaciones. Método destroy() Se llama a este método cuando el applet va a ser descargada para liberar los recursos que tenga reservados (excepto la memoria). De ordinario no es necesario redefinir este método, pues el que se hereda cumple bien con esta misión. 104 3.12.3 CAPÍTULO 3. JAVA Métodos para dibujar el applet Las applets son aplicaciones gráficas que aparecen en una zona de la ventana del browser. Por ello deben redefinir los métodos gráficos paint() y update(). El método paint() se declara en la forma: public void paint(Graphics g) El objeto gráfico g pertenece a la clase java.awt.Graphics, que siempre debe ser importada por el applet. Este objeto define un contexto o estado gráfico para dibujar (métodos gráficos, colores, fonts, etc.) y es creado por el browser. Todo el trabajo gráfico del applet (dibujo de líneas, formas gráficas, texto, etc.) se debe incluir en el método paint(), porque este método es llamado cuando el applet se dibuja por primera vez y también de forma automática cada vez que el applet se debe redibujar. En general, el programador crea el método paint() pero no lo suele llamar. Para pedir explícitamente al sistema que vuelva a dibujar el applet (por ejemplo, por haber realizado algún cambio) se utiliza el método repaint(), que es más fácil de usar, pues no requiere argumentos. El método repaint() se encarga de llamar a paint() a través de update(). El método repaint() llama a update(), que borra todo pintando de nuevo con el color de fondo y luego llama a paint(). A veces esto produce parpadeo de pantalla o flickering. Existen dos formas de evitar el flickering: 1. Redefinir update() de forma que no borre toda la ventana sino sólo lo necesario. 2. Redefinir paint() y update() para utilizar doble buffer. 3.13 CÓMO INCLUIR UN APPLET EN UNA PÁGINA HTML Para llamar a un applet desde una página HTML se utiliza la tag doble <APPLET></APPLET>, cuya forma general es (los elementos opcionales aparecen entre corchetes[]): <APPLET CODE=”miApplet.class” [CODEBASE=”unURL”] [NAME=”unName”] WIDTH=”wpixels” HEIGHT=”hpixels” [ALT=”TextoAlternativo”]> [texto alternativo para browsers que reconocen el tag <applet> pero no pueden ejecutar el applet] [<PARAM NAME=”MyName1” VALUE=”valueOfMyName1”>] [<PARAM NAME=”MyName2” VALUE=”valueOfMyName2”>] </APPLET> El atributo NAME permite dar un nombre opcional al applet, con objeto de poder comunicarse con otras applets o con otros elementos que se estén ejecutando en la misma página. El atributo ARCHIVE permite indicar uno o varios ficheros Jar o Zip (separados por comas) donde se deben buscar las clases. A continuación se señalan otros posibles atributos de <APPLET>: 1. ARCHIVE=”file1, file2, file3”. Se utiliza para especificar ficheros JAR y ZIP. 3.14. PASO DE PARÁMETROS A UN APPLET 105 (a) ALIGN, VSPACE, HSPACE. Tienen el mismo significado que el tag IMG de HTML. 3.14 PASO DE PARÁMETROS A UN APPLET Los tags PARAM permiten pasar diversos parámetros desde el fichero HTML al programa Java del applet, de una forma análoga a la que se utiliza para pasar argumentos a main(). Cada parámetro tiene un nombre y un valor. Ambos se dan en forma de String, aunque el valor sea numérico. El applet recupera estos parámetros y, si es necesario, convierte los Strings en valores numéricos. El valor de los parámetros se obtienen con el siguiente método de la clase Applet: String getParameter(String name) La conversión de Strings a los tipos primitivos se puede hacer con los métodos asociados a los wrappers que Java proporciona para dichos tipo fundamentales (Integer.parseInt(String), Double.valueOf(String), ). En los nombres de los parámetros no se distingue entre mayúsculas y minúsculas, pero sí en los valores, ya que serán interpretados por un programa Java, que sí distingue. El programador del applet debería prever siempre unos valores por defecto para los parámetros del applet, para el caso de que en la página HTML que llama al applet no se definan. El método getParameterInfo() devuelve una matriz de Strings (String[][]) con información sobre cada uno de los parámetros soportados por el applet: nombre, tipo y descripción, cada uno de ellos en un String. Este método debe ser redefinido por el programador del applet y utilizado por la persona que prepara la página HTML que llama al applet. En muchas ocasiones serán personas distintas, y ésta es una forma de que el programador del applet dé información al usuario. 3.15 CARGA DE APPLETS 3.15.1 Localización de ficheros Por defecto se supone que los ficheros *.class del applet están en el mismo directorio que el fichero HTML. Si el applet pertenece a un package, el browser utiliza el nombre del package para construir un path de directorio relativo al directorio donde está el HTML. El atributo CODEBASE permite definir un URL para los ficheros que continen el código y demás elementos del applet. Si el directorio definido por el URL de CODEBASE es relativo, se interpreta respecto al directorio donde está el HTML; si es absoluto se interpreta en sentido estricto y puede ser cualquier directorio de la Internet. 3.15.2 Archivos JAR (Java Archives) Si un applet consta de varias clases, cada fichero *.class requiere una conexión con el servidor de Web (servidor de protocolo HTTP), lo cual puede requerir algunos segundos. En este caso es conveniente agrupar todos los ficheros en un archivo único, que se puede comprimir y cargar con una sola conexión HTTP. 106 CAPÍTULO 3. JAVA Los archivos JAR están basados en los archivos ZIP y pueden crearse con el programa jar que viene con el JDK. Por ejemplo: jar cvf myFile.jar *.class *.gif crea un fichero llamado myFile.jar que contiene todos los ficheros *.class y *.gif del directorio actual. Si las clases pertenecieran a un package llamado es.ceit.infor2 se utilizaría el comando: jar cvf myFile.jar es\ceit\infor2\*.class *.gif 3.16 APPLETS QUE TAMBIÉN SON APLICACIONES Es muy interesante desarrollar aplicaciones que pueden funcionar también como applets y viceversa. En concreto, para hacer que un applet pueda ejecutarse como aplicación pueden seguirse las siguientes instrucciones: 1. Se añade un método main() a la clase MiApplet (que deriva de Applet) 2. El método main() debe crear un objeto de la clase MiApplet e introducirlo en un Frame. 3. El método main() debe también ocuparse de hacer lo que haría el browser, es decir, llamar a los métodos init() y start() de la clase MiApplet. 4. Se puede añadir también una static inner class que derive de WindowAdapter y que gestione el evento de cerrar la ventana de la aplicación definiendo el método windowClosing(). Este método llama al método System.exit(0). Según como sea el applet, el método windowClosing() previamente deberá también llamar a los métodos MiApplet.stop() y MiApplet.destroy(), cosa que para las applets se encarga de hacer el browser. En este caso conviene que el objeto de MiApplet creado por main() sea static, en lugar de una variable local. A continuación se presenta un ejemplo: public class MiApplet extends Applet { ... public void init() {...} ... // clase para cerrar la aplicación static class WL extends WindowsAdapter { public void windowClosing(WindowEvent e) { MiApplet.stop(); MiApplet.destroy(); System.exit(0); } } // fin de WindowAdapter // programa principal public static void main(String[] args) { static MiApplet unApplet = new MiApplet(); Frame unFrame = new Frame(”MiApplet”); unFrame.addWindowListener(new WL()); unFrame.add(unapplet, BorderLayout.CENTER); unFrame.setSize(400,400); 3.16. APPLETS QUE TAMBIÉN SON APLICACIONES unApplet.init(); unApplet.start(); unFrame.setVisible(true); } } // fin de la clase MiApplet 107 Capítulo 4 Herramientas utilizadas 4.1 Netbeans La plataforma NetBeans permite que las aplicaciones sean desarrolladas a partir de un conjunto de componentes de software llamados módulos. Un módulo es un archivo Java que contiene clases de java escritas para interactuar con las APIs de NetBeans y un archivo especial (manifest file) que lo identifica como módulo. Las aplicaciones construidas a partir de módulos pueden ser extendidas agregándole nuevos módulos. Debido a que los módulos pueden ser desarrollados independientemente, las aplicaciones basadas en la plataforma NetBeans pueden ser extendidas fácilmente por otros desarrolladores de software. NetBeans es un proyecto de código abierto de gran éxito con una gran base de usuarios, una comunidad en constante crecimiento, y con cerca de 100 socios en todo el mundo. Sun MicroSystems fundó el proyecto de código abierto NetBeans en junio 2000 y continúa siendo el patrocinador principal de los proyectos. 4.1.1 La Plataforma NetBeans La Plataforma NetBeans es una base modular y extensible usada como una estructura de integración para crear aplicaciones de escritorio grandes. Empresas independientes asociadas, especializadas en desarrollo de software, proporcionan extensiones adicionales que se integran fácilmente en la plataforma y que pueden también utilizarse para desarrollar sus propias herramientas y soluciones. La plataforma ofrece servicios comunes a las aplicaciones de escritorio, permitiéndole al desarrollador enfocarse en la lógica específica de su aplicación. Entre las características de la plataforma están: • Administración de las interface de usuario (ej. menús y barras de herramientas). • Administración de las configuraciones del usuario. • Administración del almacenamiento (guardando y cargando cualquier tipo de dato). • Administración de ventanas. • Framework basado en asistentes (diálogos paso a paso). 109 110 4.2 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS NetBeans IDE El IDE NetBeans es un IDE - una herramienta para programadores pensada para escribir, compilar, depurar y ejecutar programas. Está escrito en Java - pero puede servir para cualquier otro lenguaje de programación. Existe además un número importante de módulos para extender el IDE NetBeans. El IDE NetBeans es un producto libre y gratuito sin restricciones de uso. El NetBeans IDE es un IDE de código abierto escrito completamente en Java usando la plataforma NetBeans. El NetBeans IDE soporta el desarrollo de todos los tipos de aplicación Java (J2SE, web, EJB y aplicaciones móviles). Entre sus características se encuentra un sistema de proyectos basado en Ant, control de versiones y refactoring. NetBeans IDE 6.5, la cual fue lanzada el 19 de Noviembre de 2008, extiende las características existentes del Java EE (incluyendo Soporte a Persistencia, EJB 3 y JAX-WS). Adicionalmente, el NetBeans Enterprise Pack soporta el desarrollo de Aplicaciones empresariales con Java EE 5, incluyendo herramientas de desarrollo visuales de SOA, herramientas de esquemas XML, orientación a web servicies (for BPEL), y modelado UML. El NetBeans C/C++ Pack soporta proyectos de C/C++, mientras el PHP Pack, soporta PHP 5. Modularidad Todas las funciones del IDE son provistas por módulos. Cada módulo provee una función bien definida, tales como el soporte de Java, edición, o soporte para el sistema de control de versiones. NetBeans contiene todos los módulos necesarios para el desarrollo de aplicaciones Java en una sola descarga, permitiéndole al usuario comenzar a trabajar inmediatamente. Sun Studio, Sun Java Studio Enterprise, y Sun Java Studio Creator de Sun Microsystems han sido todos basados en el IDE NetBeans. Desde Julio de 2006, NetBeans IDE es licenciado bajo la Common Development and Distribution License (CDDL), una licencia basada en la Mozilla Public License (MPL). 4.3 Creación de proyecto 1) File / New Proyect (o Ctrl Mayúscula N), ver figura 4.1 de la pág.111. en el cuadro de dialogo New Project elegimos Java y Java ClassLibrary y seguidamente hacemos clic sobre el botón NEXT , ver Figura 4.2 en la pág. 111. en el cuadro de diálogo New Java Class Librery tenemos que rellenar los siguientes campos • Project Name: Hilos • Project Location: C:\Tesis\hilos vamos a hacer clic sobre el botón Browser para indicar que queremos que nuestro proyecto se aloje por debajo de los directorios C:\Tesis\hilos seguidamente hacemos clic sobre el botón Finish; ver Figura 4.3 en la pág. 112. 4.3. CREACIÓN DE PROYECTO Figura 4.1: Nuevo proyecto Figura 4.2: Nuevo proyecto paso 2 111 112 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.3: Nuevo proyecto paso 3 4.4 Creación de un Package Cuando se esta realizando aplicaciones de cierta envergadura,se tiene que incluir las Clases de nuestra aplicación en paquetes (packages) para poder obtener una serie de ventajas. • estos paquetes tienen sentido tanto en el proceso de desarrollo como en el de producción • los paquetes no están ligados a un entorno de desarrollo, sino que es una parte integral y esencial del lenguaje Java En este caso, se creara un paquete llamado PackHilo siguiendo los siguientes pasos, situese en la ventana Projects ,con el botón derecho del mouse seleccionara la carpeta Source Packages correspondiente al proyecto Hilos que se acaba de crear, se elegira NewJava Package ( ver figura 4.4 de la pág. 113 ). y en el cuadro de diálogo New Java Package se introduce el nombre del paquete PackHilo y se hace clic sobre el botón Finish; ver figura 4.5 de la pág. 114. 4.5 Creación del applet 1. Seleccionar el paquete,sobre este hacer click con el botón derecho del mouse NewApplets,(ver figura 4.6 de la pág. 115). 2. Fijamos el nombre del Applet y luego presionamos el botón Finish. 4.5. CREACIÓN DEL APPLET Figura 4.4: Creando un paquete 113 114 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.5: Creacion de paquete paso 2 4.6. CREACIÓN DE LA PÁGINA HTML 115 3. El editor automaticamente genera un código que hay que rellenar con el código que se necesite, (ver figura 4.8 de la pág. 117). Figura 4.6: Creacion del applet paso 1 Una vez creado el applets se debe crear la página web que va a contener a este. Se debe crear un archivo HTML dentro del paquete que contiene el applet. 4.6 Creación de la página HTML 1. Seleccionar el paquete,sobre este hacer click con el botón derecho del mouse NewHTML File... 2. Fijamos el nombre del HTML y presionamos el botón Finish. 3. Desaparecerá el asistente para crear un archivo HTML y aparecerá lo mostrado en la figura 4.11 de la pág.119.Del lado derecho aparece el editor de NetBeans con el esqueleto del HTML: HilosJava.html, mientras que del lado izquierdo aparece el árbol del proyecto Hilos. Este fichero html debe contener una marca que especifica el código que cargará el appletviewer:<applet name=”Hilojava.class” width=”300” height=”200”> ver figura 4.11 de la pág.119. 116 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.7: Creacion del applets paso 2 4.7 Ejecución de un Applets 1. Para ejecutar la aplicación dentro de NetBeans, seleccione el archivo .java,en este caso Hilo.java, con el botón derecho del mouse debe hace clik en Run File como se muestra en la figura 4.12 de la pág.120 2. Los resultados arrojados al ejecutar la aplicación se muestran la ventana: Appletviewer,en la parte superior de la ventana de NetBeans, como se muestra en la figura 4.13 del pág.120. 3. Para ejecutar una aplicación desde una consola del sistema, se tecleara en la consola: java - jar ruta\nombreProyecto.jar, antes se debe crear el archivo jar ,donde ruta\nombreProyecto.jar es la ruta y nombre del archivo .jar. Para este ejemplo ruta \nombreProyecto .jar es: C: \Tesis \Hilos \dist \Hilos.jar. 4.8 Como crear un archivo jar con Netbeans Archivos JAR (”Java Archives”) Una archivo JAR es simplemente un archivo comprimido que incluye una estructura de directorios con Clases, lo anterior permite: • Distribuir/Utilizar Clases de una manera eficiente a través de un solo archivo. 4.8. COMO CREAR UN ARCHIVO JAR CON NETBEANS Figura 4.8: Creaccion de applet paso 3 117 118 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.9: Creacion del HTML paso 1 4.8. COMO CREAR UN ARCHIVO JAR CON NETBEANS Figura 4.10: Creacion del HTML paso 2 Figura 4.11: Creacion del HTML paso 3 119 120 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.12: Ejecutar un Applet Figura 4.13: Visualizando el applet en el appletviewer 4.8. COMO CREAR UN ARCHIVO JAR CON NETBEANS 121 • Declarar dichas Clases de una manera más eficiente en la variable CLASSPATH. En todo JDK/J2SE se incluye el comando jar el cual permite generar, observar y descomprimir archivos JAR. Para poder generar un archivo .jar con Netbean ,primero hay que ver si esta configurado el proyecto para poder generlo. 1) Se debe hacer click con el boton derecho del mouse sobre el proyecto (en este caso Hilos) seleccione Propiedades, ver figura 4.14 de la pág. 121. Figura 4.14: Propiedades de un proyecto 2) En el cuadro de dialogo de Proyect Propieties en la categoria Packaging debe estar tildado Compress JAR file. y en Jar file especifica donde se ubicara el ejecutable 122 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS .jar.(dist/Hilos.jar) ver figura 4.15 pág. 122. Figura 4.15: Propiedades del Proyecto Para generar un jar de una aplicación sencilla solo debe hacer clickcon el bóton derecho del mouse sobre el proyecto -> Clean and Build ver figura 4.16 de la pág.123. Une vez que se ejecuto Clean and Build en la pantalla de salida Output mostrara lo siguiente,ver figura 4.17 de la pág.123. En el panel de Archivos(Files) se podra visualizar el archivo JAR dentro de la carpeta dist, ver figura 4.18 de la pág. 124. Ahora cada vez que se desee ejecutar el proyecto sin abrir el netbeans solo bastará con hacer doble clic en el archivo JAR y listo. 4.9 Adobe Dreamweaver CS3 4.9.1 Qué es Dreamweaver CS3? Dreamweaver CS3 es un software fácil de usar que permite crear páginas web profesionales. Las funciones de edición visual de Dreamweaver CS3 permiten agregar rápidamente diseño y funcionalidad a las páginas, sin la necesidad de programar manualmente el código HTML. Se puede crear tablas, editar marcos, trabajar con capas, insertar comportamientos JavaScript, etc., de una forma muy sencilla y visual. Además incluye un software de cliente FTP completo, permitiendo entre otras cosas trabajar con mapas visuales de los sitios web, actualizando el sitio web en el servidor sin salir del programa. 4.9.2 Novedades de Dreamweaver CS3 Las características que aporta esta nueva versión sobre la anterior. 4.9. ADOBE DREAMWEAVER CS3 Figura 4.16: Generar un archivo jar-Clean and Build Figura 4.17: Outup del proyecto al generar el archivo jar 123 124 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.18: Proyecto - dist -Hilos.jar 4.10. ENTORNO DE TRABAJO 125 • Mejoras en Spry. El ”Framework” o estructura Spry ha recibido un fuerte impulso en esta versión de Dreamweaver. Spry es un conjunto de archivos JavaScript que permiten la inclusión de elementos dinámicos en las páginas HTML. Por ejemplo se pueden incluir acordeones, barras de menus, validación de formularios, acceso a datos XML, etc. También se han incluido efectos spry que se aplican a elementos ya existentes en la página HTML para hacer que se desvanezcan, reduzcan su tamaño, se resalten, etc. • Mayor integración con Photoshop y Fireworks. Ahora es posible pegar directamente imágenes desde Photoshop en una página HTML de Dreamweaver. Luego con un doble clic podremos ir a editar la imagen en Photoshop. Se pueden importar imágenes con capas. • Mejoras en la comprobación de la compatiblidad con diferentes navegadores. Dreamweaver CS3 puede generar informes con los problemas de visualización de elementos CSS en los navegadores más utilizados. • Adobe CSS Advisor es un sitio web accesible desde Dreamweaver que contiene información útil para resolver los problemas de compatibilidad entre navegadores. • Mejoras en CSS. La administración de CSS es más fácil, ahora se pueden trasladar elementos CSS entre diferentes hojas de estilo. También ha aumentado la cantidad de plantillas CSS disponibles para aplicar a nuestras páginas web. bola Adobe Device Central, incluido en la Adobe Creative Suite, facilita la publicación en dispositivos móviles, PDAs, etc. 4.10 Entorno de trabajo 4.10.1 Pantalla Principal Al arrancar Dreamweaver aparece una pantalla inicial como se ve en la figura 4.19 de la pág.126 vamos a ver sus componentes fundamentales. 4.10.2 La barra de título La barra de título contiene el nombre del programa (Marcromedia Dreamweaver CS3) y seguidamente el nombre del documento que aparecerá en el explorador y entre paréntesis, su ubicación y el nombre del archivo en formato html. En el extremo de la derecha están los botones para minimizar, maximizar/restaurar y cerrar. Barra de titulo 126 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.19: Pantalla principal del Dreamweaver Cs3 4.10. ENTORNO DE TRABAJO 4.10.3 127 La barra de menús La barra de menús contiene las operaciones de Dreamweaver, agrupadas en menús desplegables. Al hacer clic en Insertar, por ejemplo, veremos las operaciones relacionadas con los diferentes elementos que se pueden insertar en Dreamweaver. Muchas de las operaciones se pueden hacer a partir de estos menús, pero para algunas es preferible o indispensable hacerlas desde los paneles. Figura 4.20: Barra de menues 4.10.4 La barra de herramientas estándar Figura 4.21: Barra de Herramientas estándart La barra de herramientas estándar contiene iconos para ejecutar de forma inmediata algunas de las operaciones más habituales, como Abrir , Guardar , etc. 4.10.5 La barra de herramientas de documento Figura 4.22: Barra de herramienta del documento La barra de herramientas de documento contiene iconos para ejecutar de forma inmediata algunas otras operaciones habituales que no incluye la barra de herramientas estándar. Estas operaciones son las de cambio de vista del documento, vista previa, etc. 4.10.6 La barra de estado La barra de estado nos indica en cada momento en qué etiqueta HTML nos encontramos (en la imagen al encontrarnos en un documento en blanco estamos directamente sobre la etiqueta <body>). También nos es posible alternar entre los modos de selección, mano (para arrastrar la página), o zoom. En cualquier momento puedes seleccionar el zoom preferido desde el desplegable zoom y ajustar la vista al porcentaje preferido (por defecto siempre viene al 100%). 128 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.23: Barra de Estado 4.10.7 Los paneles e inspectores Dreamweaver utiliza ventanas flotantes similares a las barras de herramientas, que se conocen como paneles o inspectores. La diferencia entre panel e inspector es que, en general, la apariencia y opciones de un inspector cambian dependiendo del objeto seleccionado. A través de la opción Ventana, de la barra de menús, es posible mostrar u ocultar cada uno de los paneles o inspectores. Vamos a ver los más importantes. 4.10.8 El inspector de Propiedades Figura 4.24: Panel de inspector de propiedades El inspector de Propiedades muestra y permite modificar las propiedades del elemento seleccionado que son usadas de forma más frecuente. Por ejemplo, cuando el elemento seleccionado sea texto mostrará el tipo de fuente, la alineación, si está en negrita o cursiva, etc. Pulsando sobre el botón se despliega para mostrar más opciones. Este botón se encuentra en la esquina inferior-derecha. Seguramente es la herramienta de Dreamweaver que más se utiliza. 4.10.9 La barra de herramientas Insertar o panel de objetos La barra de herramientas Insertar o panel de objetos permite insertar elementos en un documento sin la necesidad de recurrir al menú Insertar. Los elementos están clasificados según su categoría: tablas, texto, objetos de formulario, etc. Es posible configurar este panel para que en los botones se muestren los iconos de los objetos (como ocurre en la figura4.25), para que se muestren los nombres de los objetos, o para que se muestren ambos a la vez. 4.10.10 Vistas de un documento Puedes cambiar la vista del documento a través de la barra de herramientas de documento. 4.10. ENTORNO DE TRABAJO Figura 4.25: Barra de herramientas Insertar o Panel de objetos Figura 4.26: Barra de herramienta del documento 129 130 4.10.11 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS La vista de Diseño La vista Diseño permite trabajar con el editor visual. Es la vista predeterminada de Dreamweaver y la que se suele utilizar habitualmente. Figura 4.27: Vista de Diseño Dreamweaver 4.10.12 La vista código La vista Código se utiliza para poder trabajar en un entorno totalmente de programación, de código fuente. No permite tener directamente una referencia visual de cómo va quedando el documento según se va modificando el código. 4.10.13 La vista Código y Diseño La vista Código y Diseño permite dividir la ventana en dos zonas. La zona superior muestra el código fuente, y la inferior el editor visual. Cuando se realiza un cambio en alguna de las zonas, este cambio se aplica directamente sobre la otra. 4.10. ENTORNO DE TRABAJO Figura 4.28: Vista de código en Dreamweaver 131 132 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.29: Vista de diseño y codigo 4.11. COMO CREAR UN PÁGINA HTML CON DREAMWEAVER CS3 4.11 133 Como crear un página HTML con Dreamweaver CS3 1. Seleccionar la opción File ->New.. Al hacer esto se abrirá el cuadro de dialogo de New Document.En la lista de categorías de la izquierda se elige Página en blanco(Blank Page): Tipo de página HTML y Diseño <ninguno>(<none>) 2. Se debe hacer click en Create y listo, (ver figura 4.30 de la pág. 133). Figura 4.30: Nuevo Documento HTML También se podrá crear un nuevo documento HTML con la ventana de Bienvenida ver figura4.31,al hacerse clic sobre la opción HTML ,automaticamente genera un HTML sin titulo(Untitled-1) ,según la vista de código se visualizara lo siguiente, ver figura4.32 Se debe guardar este documento nuevo para que esté localizado físicamente en alguna carpeta del sistema (en concreto, en la carpeta del sitio Web en el que se este por trabajar). Para guardar una página nueva los pasos a seguir serán: (a) Seleccionar File > Save o hacer clic sobre el botón herramientas Estándar. de la barra de (b) En el cuadro de diálogo Save AS, accedemos a la carpeta raíz del sitio (en nuestro ejemplo, la carpeta Sitio ). Aparecerá por defecto la carpeta raíz del sitio que tengamos abierto en el Panel Archivos; ver figura 4.33 de la pág. 136. 1. Se introduce el nombre de archivo .html ( por ejemplo; Prueba.html) 134 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.31: Ventana de Bienvenida del Dramweaver 2. Luego se hace clic en Guardar. El nombre de archivo y su localización en la carpeta del sitio aparecerán en la barra de título de la ventana de DW. Nombre de archivo 4.11.1 Ubicación del HTML Propiedades de la página. 1. Ir al menú Modify ,seleccionar la opción Page properties,ver figura4.34 de la pág. 137, el cual desplegará el cuadro Page Propierties, ver figura 4.35 de la pág. 137. 2. Se puede cambiar el Título de la página modificándolo en la categoría Title/Encoding. 3. Modificará el color de fondo en la categoría Appearance , en la opción Background color , se puede seleccionar el color que se desee de la paleta de colores que se despliega , ver figura4.36 de la pág.138. 4. Se puede cambiar el tipo y tamaño de fuente dentro de la categoría Appearance, ver figura4.37 de la pág.138. 5. Luego de configurar la página como se desea, se hace clic en el botón OK. 4.11. COMO CREAR UN PÁGINA HTML CON DREAMWEAVER CS3 135 Figura 4.32: Documento Html sin titulo. 4.11.2 Insertar una imagen con Dreamweaver Para insertar una imagen se debe ir a al menú Insertar elegir la opción Imagen, el cual desplegara el siguiente ventana, ver figura 4.39 de la pág.139. También se puede insertar la imagen a través del barra de herramientas,como se ve en la figura 4.38 de la pág.139. 4.11.3 Insertar un Vinculo 1. Sitúa el cursor en la zona del documento que quieres que aparezca el hipervínculo 2. Realiza una de estas dos operaciones para mostrar el cuadro de dialogo Hipervínculo: • Vamos al menú Insertar > Hyperlink4.40 • Pulsamos sobre el botón Hipervínculo desplegara la siguiente ventana4.41. del panel Insertar > Common, el cual Para realizar un enlace simple basta con rellenar estos campos de texto: • Texto : el texto que se mostrará como hipervínculo en el documento. • Vinculo : la dirección URL del vínculo o haga clic en el icono de carpeta localizar y seleccionar un archivo dentro del sitio web. • Destino : Lo explicaremos detenidamente al final de esta Unidad. para 136 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.33: Ventana de Guardar Como. 4.11. COMO CREAR UN PÁGINA HTML CON DREAMWEAVER CS3 137 Figura 4.34: Propiedades de la página HTML Figura 4.35: Configuración de las propiedades de la página • Título: Escribiremos un texto alternativo que se muestra en un letrero amarillo (ver figura 4.41 de la pág. 140. 4) Aceptar y se obtiene este resultado 4.11.4 . Vista previa del HTML Para poder visualizar nuestras páginas web, existe la opción de la Vista previa(File >Preview in Browser). En esta lista de navegadores podrás seleccionar el navegador con el que se desee realizar la vista previa. También podrás Editar esta lista en la opción Edit Browser List. 138 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.36: Paleta de Colores de Fondo del la página Figura 4.37: Tamaño y tipo de fuente de la página Vista previa del HTML Dreamweaver CS3 incorpora una nueva opción que te permitirá tener una vista previa de la Web en diferentes marcas y modelos de teléfonos celulares, esta opción se llama Device Central. Figura 4.38: Insertar -Barra de herramientas Figura 4.39: Insertar una imagen 140 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Figura 4.40: Insertar un Hyperlink desde el menu. Figura 4.41: Configuracion Hyperlik 4.11. COMO CREAR UN PÁGINA HTML CON DREAMWEAVER CS3 Figura 4.42: Seleccionar archivo para el enlace 141 142 CAPÍTULO 4. HERRAMIENTAS UTILIZADAS Capítulo 5 Algoritmos de Planificación del Procesador Para ingresar al aplicativo a través de Internet desde un navegador ( Exlporer o FireFox) escriba la siguiente dirección en la barra de direcciones: http://guarani.dch.unne.edu.ar/classes Figura 5.1: Barra de dirección del navegador La página se mostrará de la siguiente manera:ver figura 5.2 de la pág.144. Si su pc no posee Java podra descargarlo e instalarlo seleccionando el bóton: Si no posee Flass player podra descargarlo e instalarlo seleccionando el bóton , este permite visualizar el reloj. Para poder acceder a la teoría de los Algoritmos de Planificación del procesador ,deberá presionar el botón de la figura 5.3 de la pág. 144, a continuación mostrara la siguiente pantalla,ver figura5.4 de la pág.145. Una vez que este en esta página podrá acceder a los distintos algoritmos haciendo clic en el enlace , el cual ejecutará el applet del algoritmo que haya seleccionado, por ejemplo si eligió Algoritmo de planificación F.I.F.O, mostrará la página siguiente, ver figura5.5 de la pág. 146. En la página le aparecerá un cuadro de dialogo, que le pedirá que ingrese la cantidad de procesos a ejecutar,ver figura 5.6 de la pág.146,una vez realizado esto le solicitará que cargue los tiempo de ejecución de cada unos de los procesos, ver figura 5.7 de la pág.147 . 143 144 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Figura 5.2: Página Principal Figura 5.3: Botón de Algortimo de Planificacion de Procesos Una vez realizado esto podrá visualizar los resultado, ver figura 5.8 de la pág.147 . Para poder acceder a la teoría da Hilos de Java,deberá presionar el botón ,ver figura5.9 de la pág.148 . luego visualizara la siguiente página, ver figura 5.10 de la pág.148. Para poder ejecutar la aplicación realizada en Java, deberá hacer clic en el enlace ,a continuación mostrara el cuadro de dialogo, ver figura 5.11 de la pág. 149, si desea ejecutar directamente el archivo, debe hacer clic en el botón Aceptar, en caso contrario si desea guardar el archivo para luego ejecutarlo desde su Pc, se debe seleccionar la opción Guardar archivo, el cual se descargara por defecto si es un navegador FireFox en la carpeta Mis Documentos/Descargas. En el caso que su navegador sea el Explorer el cuadro de dialogo que visualizara es el siguiente: Si desea guardar el archivo le mostrara el cuadro de dialogo de la figura 5.11,donde 5.1. COMO MONTAR LA PÁGINA WEB AL SERVIDOR 145 Figura 5.4: Página de los Algoritmos deberá especificar donde desea guardar. En el caso de ejecutar directamente se debe hacer clic en el botón Abrir. Una vez que se ha decidió ejecutar la aplicación en Java ,se visualizará la siguiente ventana: Luego se debe cargar los datos de configuración, para ello seleccione Configuración y Ejecución, se desplegara una lista, seleccione Datos de configuración.. a continuación visualizara la ventana ,ver figura se debe ingresar en numero incial de buffer ocupados, los demás datos esta preestablecidos, luego se hace clic en el botón Aceptar. Luego mostrara los datos ingresados. Para poder realizar la ejecución se debe seleccionar de la lista de Configuración y ejecución -> Ejecución Concurrente e Hilos Podrá ver a continuación el cuadro siguiente; ver figura 5.19 de la pág.153. Si hace clic en Datos de Configuración -> Listado de resultados de Ejecución, podrá visualizar el resultado obtenido de la ejecución; ver figura 5.20 de la pág. 154. Para salir del Sistema se debe seleccionar la opción Salir-> Salir del Sistema; ver figura 5.21 de la pág.154. 5.1 Como montar la página web al servidor Tunnelier es un cliente SSH rápido, robusto, fácil de usar para Windows (todas las versiones) con un cliente de transferencia de ficheros SFTP gráfico. 146 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Figura 5.5: Algoritmo de Planificacion F.I.F.O. Figura 5.6: Cuadro de entrada de cantidad de procesos 5.1. COMO MONTAR LA PÁGINA WEB AL SERVIDOR Figura 5.7: Cuadro de entrada del tiempo de los procesos. Figura 5.8: Resultado del Algoritmo Fifo 147 148 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Figura 5.9: Botón Hilos de Java Figura 5.10: Página de Hilos de java 1. Abrir el Tunnerlier,Inicio-Todos los programas-Bitvise Tunnelier-Tunnerlier. 2. Se debe especificar el Host (en este caso guarani.dch.unne.edu.ar); ver figura 5.22 de la pág. 155. 3. Ingresar el Username y password, luego hacer clic en el botón Login, luego se visualizara el siguiente cuadro de dialogo, se debe hacer clic en el botón Accept and Save; ver figura 5.23 de la pág. 156. 4. Podrá visualizar tanto los archivos locales como los archivos remotos(servidor). ver figura 5.24 de la pág. 156. 5. Seleccione la carpeta que contiene los archivos de la página web, y arrastrelo dentro de la carpeta /var/www/classes del archivo del servidor web y listo; ver figura 5.25 de la pág. 157. Figura 5.11: Abriendo ejecutable de Hilos en Java Figura 5.12: Cuadro de Dialogo con navegador Explorer 150 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Figura 5.13: Cuadro Guardar Como Figura 5.14: Ventana principal 5.1. COMO MONTAR LA PÁGINA WEB AL SERVIDOR Figura 5.15: Menú Configuración y Ejecución ->Datos de Configuración. Figura 5.16: Ventana de Configuración 151 152 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Figura 5.17: Ventana de Carga de Datos. Figura 5.18: Menú Configuración y Ejecución -> Ejecución Concurrente e Hilos 5.1. COMO MONTAR LA PÁGINA WEB AL SERVIDOR Figura 5.19: Ventana Realizar Ejecución Concurrente e Hilos. 153 154 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Figura 5.20: Ventana Lista de Resultados de Ejecución Concurrente e Hilos. Figura 5.21: Ventana Principal-Menú Salir 5.1. COMO MONTAR LA PÁGINA WEB AL SERVIDOR Figura 5.22: Ventana Principal Tunnelier 155 156 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Figura 5.23: Cuadro de Verificacin del HOST Figura 5.24: Ventana de Local File y Remote File 5.1. COMO MONTAR LA PÁGINA WEB AL SERVIDOR Figura 5.25: Ventana Local File y Remote File pasando los archivos. 157 158 CAPÍTULO 5. ALGORITMOS DE PLANIFICACIÓN DEL PROCESADOR Capítulo 6 Conclusión Se ha desarrollado un entorno interactivo web que ayuda a los usuarios a entender el comportamiento de los Sistemas Operativos a trevés del analisis de los algoritmos de planificación del procesador: • Los algoritmos apropiativos — Round Robin — S.R.T • Los algoritmos no apropiativos — F.I.F.O — S.J.F. Este aplicativo se ha desarrollado utilizando el lenguaje de programacion Java mediante Applets.El applet desarrollado no realiza la grabación de la simulación en un archivo,sino que muestra los datos del resultado de la simulación en una pantalla dentro del mismo applet,los cuales se pierden al cerrar el applet. En cuanto a la aplicación Concurrencia e Hilos con Java proporcionado por el Magister La Red Matinez se realizo una adaptación para que pueda ser ejecutado desde la aplicación web, esto se logro haciendo un compresión de la aplicación en un archivo .jar, para ello requerira que se instale en el cliente la Maquina Virtual. Actividades futuras. Mejorara el entorno gráfico de los distintos algortimos,agregar más algoritmos. Utilizar Servlets en vez de Applets, para asi poder guardar los resultados en base de datos, y poder realizar comparaciones o estadisticas con los resultados obtenidos con los distintos algoritmos. 159 Bibliografía [1] L. Joyanes Aguilar. Fundamentos de Programación - Algoritmos y Estructura de Datos - Segunda Edición. Mc Graw Hill/Interamericana de España, S.A.U., España, 1996. [2] L. Joyanes Aguilar. Programación Orientada a Objetos - Segunda Edición. Mc Graw Hill/Interamericana de España, S.A.U., España, 1998. [3] L. Joyanes Aguilar; L. Rodríguez Baena; M. Fernández Azuela. Fundamentos de Programación - Libro de Problemas. Mc Graw Hill/Interamericana de España, S.A.U., España, 1996. [4] H. M. Deitel. Introducción a los Sistemas Operativos. Addison-Wesley Iberoamericana, México, 1987. [5] D. L. la Red Martinez. Sistemas Operativos. EUDENE, Argentina, 2004. [6] L. Joyanes Aguilar; I. Zahonero Martínez. Estructura de Datos - Algoritmos, Abstracción y Objetos. Mc Graw Hill/Interamericana de España, S.A.U., España, 1998. [7] J. L. Peterson; A. Silberschatz. Operating Systems Concepts. Addison-Wesley, MAUSA, 1991. [8] E. Castillo; A. Cobo; P. Gómez; C. Solares. JAVA - Un Lenguaje de Programación Multiplataforma para Internet. Paraninfo, España, 1997. [9] A. S. Tanenbaum. Operating Systems: Design And Implementation. Prentice Hall, NJ-USA, 1987. [10] A. S. Tanenbaum. Sistemas Operativos Modernos. Prentice Hall Hispanoamericana, S.A., México, 1993. [11] A. S. Tanenbaum. Sistemas Operativos Distribuidos. Prentice Hall Hispanoamericana, S.A., México, 1996. [12] A. S. Tanenbaum. Redes de Computadoras. Prentice Hall Hispanoamericana S. A., México, 1997. 161 Índice de Materias árbol de procesos, 7 algoritmos de programación del, 29 bucles, 87 do while, 88 for, 88 while, 87 algoritmo de planificación, 15 algoritmos de búsqueda en disco algoritmo del elevador, 30 primero en llegar primero en ser atendido, 29 primero la búsqueda más corta, 30 almacenamiento auxiliar, 25 real, 24 almacenamiento de niveles múltiples organización del, 24 almacenamiento virtual, 14 conceptos básicos, 23 API (Application Programming Interface), 79 aplicación interactiva, 95 archivo, 28 archivos, 6, 27 arrays, 92 AWT concepto, 94 interface gráfica de usuario, 94 C-SCAN, 60 C/C++, 86 código Hamming, 32 cargas pesadas, 23 Clase, 77 clase, 89 características, 90 clase object, 91 clases de utilidad, 92 clase Arrays, 92 clases string y StringBuffer, 93 Double, 93 integer, 94 CMS, 11 comentarios, 86 concurrencia, 14 contiguidad artificial, 24 cpu, 5, 14, 17 cuanto, 37 búsquedas traslapadas, 31 batch, 5 bibliotecas de clases, 73 bifurcaciones, 86 if, 86 if else, 87 bits de paridad, 32 bloque try, catch, finally, 89 brazo del disco despachador de procesos, 17 despacho de procesos, 17 direcciones reales, 23 traducción de, 23 virtuales, 23 direcciones reales espacio de, 23 163 164 direcciones virtuales espacio de, 23, 24 directorio, 7 de usuarios, 28 raíz, 28 disco manejador del, 29 discos mejoras tecnológicas de los, 31 RAID, 32 dispositivo independencia del, 29 Double, 93 métodos de la clase, 94 ejemplo de arrays, 92 bifurcación if, 86 bifurcación if else, 87 bucle for, 88 bucle while, 87 clase, 78 comentario, 86 construcción de nombres de archivos en Java, 98 do while, 88 interface, 78 línea compuesta por tres sentencias, 85 método, 91 matriz, 92 operadores incrementales y relacionales, 83 programa no portable, 96 sentencia return, 89 entrada / salida, 19 introducción a la, 29 Errores de Disco, 62 errores de programación carga de drivers JDBC, 100 entrada/salida por archivo, 101 fuentes de caracteres, 101 scheduling de los hilos de ejecución, 96 terminación de líneas, 100 ÍNDICE DE MATERIAS uso de características de portabilidad, 97 uso de directorios definidos, 98 Eschenbach, 60 estructuras de programación, 85 evento, 95 sources, 95 eventos listeners, 95 expresión, 85 FCFS, 29, 59 FIFO, 37 herencia, 78, 79 Hilos y RPC, 72 HRN, 39 independencia de dispositivo, 5, 7 información acceso concurrente a la, 27 inialización de arrays, 92 instrucciones, 2 ampliadas, 6 integer, 94 métodos de la clase, 94 interface, 78 interfaz, 3 Java, 74 características, 75 conceptos, 73 conceptos básicos, 77 errores de programación, 96 estructura general de un programa, 76 introducción a, 73 Jerarquía de clases en, 79 JDK, 86, 100 latencia, 55 lenguaje de control de trabajos, 5 lenguaje de máquina, 2 listener, 95 llamada al núcleo, 8 llamadas ÍNDICE DE MATERIAS al sistema, 6 máquina virtual, 1, 6 máquinas virtuales, 10, 14 métodos, 90 de la clase object, 91 de objeto, 90 microprograma microcódigo, 2 modelo cliente - servidor, 11 modo interactivo conversacional, 5 modo núcleo modo supervisor, 8 modo usuario, 8, 12 Multics, 10 multiprocesamiento, 5, 12 multiprogramación sistemas de, 14 multiprogramación, 5, 24 Netbeans, 109 objetos del software, 6 OOP, 76, 89 operadores, 82 aritméticos, 82 de asignación, 82 de concatenación de cadenas de caracteres, 84 incrementales, 83 precedencia de, 84 racionales, 83 unarios, 82 organización interna, 8 package, 79 packages, 77 Paginación, 53 Paginación anticipada, 51 Paginación por demanda, 51 Paquetes de Hilos, 70 paralelismo, 14 PC computadoras personales, 6 planificación 165 apropiativa, 20 del procesador, 20 mecanismos de, 21 no apropiativa, 20 objetivos de la, 21 políticas de, 21 planificación apropiativa, 34 planificación no apropiativa, 34 Prioridad, 35 procesador, 15 niveles de planificación del, 20 planificación del, 19 procesadores asignación de los, 14 proceso, 14, 15 bloque de control de, 14, 17 creación de un, 18 destrucción de un, 18 estados del, 15 hijo, 18 padre, 18 reanudar un, 18 suspendido, 18 proceso cliente, 11 proceso servidor, 11 procesos, 6 algoritmo de planificación de, 19 comportamiento deseable de, 23 envejecimiento de, 22 estados de, 17 estructura jerárquica de, 18 jerarquías de, 15 lista de bloqueados, 17 lista de listos, 17 planificación de, 19 planificador de, 19 prioridad de los, 22 tabla de, 18 transiciones entre estados, 16 procesos hijo, 7 programas de aplicación, 1 programas de sistema, 1 Quantum, 38 RAID, 59 166 discos RAID, 32 recursos administrados, 3 recursos claves retención de, 22 redes de sistemas, 14 reloj de interrupción, 35 retraso o demora rotacional, 29 return do while, 89 Round Robin, 37 ruta de acceso, 7 Scan, 60 SCAN de N- Pasos, 60 search tiempo de demora rotacional, 31 seek tiempo de búsqueda, 31 seguridad, 6 sentencia, 85 seudoparalelismo, 14 sistema de archivos, 28 funciones del, 27 sistema operativo, 15, 17, 19, 29 características, 2 de red, 6 definición, 1 despachador del, 21 distribuido, 6 funciones del, 2 funciones del núcleo, 18 núcleo del, 18 objetivo primario, 1 sistemas de archivos, 27 sistemas de bases de datos, 6 sistemas de tiempo real, 5 Sistemas Distribuidos, 67 sistemas monolíticos, 8 sistemas operativos conceptos, 6 estructura, 8 generaciones, 3 historia, 3 introducción, 1 tendencias, 12 ÍNDICE DE MATERIAS SJF, 39 software, 79 spooling, 5 SRT, 39 SSF, 30 SSTF, 59 String, 93 métodos de la clase, 93 StringBuffer, 93 swing, 96 tabla de solicitudes pendientes, 29, 31 tabla de procesos, 7 tarea, 14 Terminales, 65 THE, 8 Threads, 67 tiempo de búsqueda, 29 de transferencia, 29 timesharing tiempo compartido, 5 Tipo de planificación, 36 trap, 7 Uso de Hilos, 68 variable clasificación, 79 local, 80 miembro, 81 miembro de una clase, 80 referencia, 80 variables tipo primitivo, 80 visibilidad y vida de las, 81 VM/370, 11