Aplicacion Multiproceso

23
Arquitectura y Computación Paralela Curso 2014/2015 Práctica 3 – página 1 1ª PRÁCTICA Aplicación Multiproceso sobre HTTP 1 Objetivos Se pretende que el estudiante conozca los mecanismos que proporciona el sistema operativo Unix para el desarrollo de aplicaciones multiproceso, principalmente respecto a la creación y terminación de procesos, y a su intercomunicación. También se estudiará el manejo de descriptores de E/S. 2 Desarrollo La práctica está estructurada en cuatro etapas para facilitar su desarrollo (si bien la última de ellas es opcional). Al finalizar cada etapa, el estudiante deberá entregar a través del EVA los resultados parciales alcanzados. El formato de cada entrega y las fechas correspondientes se especificarán en su momento en el entregador correspondiente. Esta práctica tiene una duración total de 6 semanas. La fecha tope para la entrega de los resultados finales de esta práctica será el viernes de la semana 7 del primer bimestre a las 12:00 horas. La entrega se realizará mediante la subida al EVA de un único fichero zip que contenga el código fuente desarrollado por el estudiante y otros ficheros que se explican más adelante. El fichero subido deberá ajustarse a las especificaciones indicadas en el entregador correspondiente. De no respetar dichas especificaciones, el profesor podrá considerar no válida la entrega. Esta práctica se realizará en grupos de 3 estudiantes como máximo, teniendo libertad los estudiantes para elegir la configuración de estos grupos. Todas las prácticas entregadas serán analizadas para detectar posibles casos de plagio. En caso de que se compruebe que existe algún caso de plagio, todos los estudiantes pertenecientes a los grupos implicados tendrán 0 puntos como calificación final de esta práctica (es decir, que no podrá presentarse a la prueba de evaluación de esta práctica) y el hecho será puesto en conocimiento de la autoridad competente para que tome las acciones pertinentes. 3 Criterios de evaluación Esta práctica tiene un peso total de 10 puntos sobre la calificación del primer bimestre repartidos de la siguiente forma: 1. Informe de la práctica que incluye el código de la aplicación (4 puntos). 2. Evaluación individual de los resultados de aprendizaje asociados a la práctica (6 puntos). 3. Hasta 2 puntos extra por la realización de las partes opcionales (1 punto por opción). 4 Enunciado Se va a desarrollar una aplicación multiproceso que podrá atender peticiones concurrentes a través del protocolo HTTP, que será desarrollada en C sobre el sistema operativo FreeBSD. A este tipo de aplicaciones se las denomina servidores web. Para realizar esta práctica, se le proporcionan los siguientes recursos (disponibles a través del EVA): un módulo de funciones para procesar el

description

Aplicacion Multiproceso

Transcript of Aplicacion Multiproceso

Page 1: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 1 ‐ 

 

1ª PRÁCTICA

Aplicación Multiproceso sobre HTTP

1 Objetivos Se pretende que el estudiante conozca los mecanismos que proporciona el sistema operativo Unix para el desarrollo de aplicaciones multiproceso, principalmente respecto a la creación y terminación de procesos, y a su intercomunicación. También se estudiará el manejo de descriptores de E/S.

2 Desarrollo La práctica está estructurada en cuatro etapas para facilitar su desarrollo (si bien la última de ellas es opcional). Al finalizar cada etapa, el estudiante deberá entregar a través del EVA los resultados parciales alcanzados. El formato de cada entrega y las fechas correspondientes se especificarán en su momento en el entregador correspondiente. Esta práctica tiene una duración total de 6 semanas.

La fecha tope para la entrega de los resultados finales de esta práctica será el viernes de la semana 7 del primer bimestre a las 12:00 horas. La entrega se realizará mediante la subida al EVA de un único fichero zip que contenga el código fuente desarrollado por el estudiante y otros ficheros que se explican más adelante. El fichero subido deberá ajustarse a las especificaciones indicadas en el entregador correspondiente. De no respetar dichas especificaciones, el profesor podrá considerar no válida la entrega.

Esta práctica se realizará en grupos de 3 estudiantes como máximo, teniendo libertad los estudiantes para elegir la configuración de estos grupos. Todas las prácticas entregadas serán analizadas para detectar posibles casos de plagio. En caso de que se compruebe que existe algún caso de plagio, todos los estudiantes pertenecientes a los grupos implicados tendrán 0 puntos como calificación final de esta práctica (es decir, que no podrá presentarse a la prueba de evaluación de esta práctica) y el hecho será puesto en conocimiento de la autoridad competente para que tome las acciones pertinentes.

3 Criterios de evaluación Esta práctica tiene un peso total de 10 puntos sobre la calificación del primer bimestre repartidos de la siguiente forma:

1. Informe de la práctica que incluye el código de la aplicación (4 puntos).

2. Evaluación individual de los resultados de aprendizaje asociados a la práctica (6 puntos).

3. Hasta 2 puntos extra por la realización de las partes opcionales (1 punto por opción).

4 Enunciado Se va a desarrollar una aplicación multiproceso que podrá atender peticiones concurrentes a través del protocolo HTTP, que será desarrollada en C sobre el sistema operativo FreeBSD. A este tipo de aplicaciones se las denomina servidores web. Para realizar esta práctica, se le proporcionan los siguientes recursos (disponibles a través del EVA): un módulo de funciones para procesar el

Page 2: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 2 ‐ 

 

protocolo HTTP y realizar las comunicaciones de red (ver apartado 4.1.5), un módulo que servirá para procesar las opciones de ejecución del programa y establecer los parámetros de configuración del servidor, y un fichero Makefile para facilitar la compilación y el enlazado de la aplicación, que será adaptado por el estudiante.

La práctica se dividirá en dos partes:

Una parte obligatoria para todos los estudiantes que abarca las funcionalidades básicas del servidor web (ver apartado 4.2).

Una parte opcional que representa algunas mejoras sobre la parte obligatoria, a elegir dentro de un catálogo propuesto en esta práctica (ver apartado 4.3).

Documentación a entregar: Se deberá entregar el programa codificado en lenguaje C, debidamente comentado y con un estilo de programación adecuado, así como cualquier otro fichero necesario para compilar y enlazar el programa, incluyendo el fichero Makefile. En la última entrega se deberá adjuntar un documento en el que se expliquen los detalles de diseño no especificados explícitamente en el enunciado de esta práctica, tanto de las funciones básicas como de las mejoras elegidas (parte opcional). Si la práctica tuviera algún error de funcionamiento conocido por el estudiante, también deberá aclararlo en el documento.

4.1 Descripción del servidor web multiproceso Para comprender mejor este apartado es interesante consultar el Apéndice A.

4.1.1 Gestión de los procesos en el servidor web multiproceso Un servidor web ha de poder atender simultáneamente muchas peticiones HTTP. Por cada documento HTML que pide un agente de usuario (navegador), se pueden desencadenar múltiples solicitudes de recursos adicionales (primero el propio documento HTML y después recursos tales como imágenes, hojas de estilos, recursos multimedia, …). Muchos agentes de usuario abren varias conexiones simultáneas con el servidor y piden en paralelo los recursos auxiliares para acelerar el proceso de descarga del documento. A cada uno de los procesos encargados de gestionar una conexión en el lado del agente de usuario se le denomina proceso cliente.

Cada petición individual lleva un cierto tiempo de servicio, que no es despreciable. Por ejemplo, el servidor ha de procesar la petición para saber qué se le está pidiendo, ha de abrir y leer el documento pedido o bien generarlo dinámicamente, y ha de transmitirlo al cliente. Si se trata de un recurso dinámico, ha de ejecutar el programa que lo genera. Todas esas operaciones pueden llevar acarreadas esperas de E/S y un cierto consumo de tiempo de CPU. Por tanto, si se desea que un servidor web atienda con diligencia a múltiples agentes de usuario a la vez, es necesario utilizar las capacidades de multiproceso o multihilo del sistema operativo para procesar concurrentemente tantas peticiones como sea posible. Aquí es donde la utilización de múltiples procesos va a venir muy bien para el desarrollo del servidor web. Otra posibilidad sería utilizar múltiples hilos.

Existen muchas formas de implementar un servidor web multiproceso. En este apartado se presentará una posible implementación partiendo de un diseño básico para que, en sucesivos refinamientos, se llegue a la solución final. En general, todas las implementaciones suponen la existencia de un proceso maestro que realiza tareas de vigilancia del estado general del servidor, y una serie de procesos auxiliares que son los que atienden a los clientes y les sirven las peticiones. En adelante se denominará procesos trabajadores a los de esta segunda categoría.

La manera más simple de gestionar los procesos trabajadores consiste en que, para cada cliente que se conecte al servidor, el proceso maestro cree un proceso trabajador nuevo y le pase la conexión en

Page 3: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 3 ‐ 

 

cuestión. Cuando se cierre la conexión, el trabajador terminará su ejecución. El inconveniente de esta técnica es que la creación y la destrucción de los procesos es una operación relativamente costosa e introduce una sobrecarga en la atención a los clientes, ya que siempre hay que esperar a que se cree un proceso trabajador antes de poder empezar a atender peticiones de un cliente.

Una posible mejora consistiría en crear, al comienzo de la ejecución del servidor web, un cierto número fijo de procesos trabajadores, que inicialmente estarían inactivos. Cuando llegue una petición de conexión de un cliente, se le asignará a uno de los procesos trabajadores inactivos, que se encargará de atender sus peticiones. Cuando se cierre la conexión con el cliente (porque el cliente decida cerrarla, porque se produzca un error, etc.), el proceso trabajador podrá finalizar también su ejecución y crearse otro proceso nuevo para sustituirlo, o bien el proceso trabajador podrá volver al estado inactivo y reutilizarse para procesar conexiones futuras. En este caso, la sobrecarga es mucho menor, ya que no hay que esperar a que se cree un proceso nuevo para las conexiones que llegan. Ahora bien, puede darse el caso de que todos los procesos trabajadores estén ocupados cuando llega una conexión nueva, lo cual demoraría la atención de dicha conexión hasta que alguno de los procesos trabajadores quede libre.

Un refinamiento de la técnica anterior consistiría en crear inicialmente un cierto número de procesos trabajadores, pero con la posibilidad de crear más procesos, si en un momento dado todos están ocupados y llegan más peticiones de conexiones de clientes. Al igual que en el caso anterior, los procesos que terminen con sus conexiones pasarán nuevamente al estado inactivo a la espera de que haya trabajo para ellos.

Un inconveniente de usar el método anterior es que, si durante un cierto intervalo de tiempo se produce un pico de conexiones, es probable que el servidor web cree muchos procesos trabajadores. Cuando el pico haya sido atendido, quedará un gran número de procesos trabajadores inactivos consumiendo recursos del sistema. La solución a este problema consiste en hacer que el proceso maestro, si ve que hay demasiados procesos trabajadores inactivos, dé orden a algunos de ellos para que finalicen.

Resumiendo todo lo anterior, el servidor web a desarrollar debe cumplir los siguientes requisitos respecto a la gestión del servicio:

El servidor constará de un proceso maestro y un número variable de procesos trabajadores.

El proceso maestro vigilará periódicamente el estado de los procesos trabajadores y creará o destruirá procesos trabajadores según sea necesario.

Los procesos trabajadores estarán en un bucle en el que esperarán a que se conecte un cliente y, entonces, atenderán todas sus peticiones hasta la desconexión del cliente. No atenderán a más clientes hasta que se desconecte el cliente actual.

Inicialmente, el proceso maestro creará un número Pini de procesos trabajadores.

Si el proceso maestro detecta que hay menos de Pinact_min procesos trabajadores inactivos, entonces creará procesos trabajadores adicionales hasta llegar a tener Pinact_min procesos trabajadores inactivos o se alcance el límite de Pmax procesos trabajadores.

Si el proceso maestro detecta que han quedado más de Pinact_max procesos trabajadores inactivos, ordenará la terminación de varios de esos procesos inactivos, hasta alcanzar el tope de Pinact_max procesos trabajadores inactivos.

Para finalizar la ejecución del servidor web, el proceso maestro dará la orden a todos los procesos trabajadores para que, cuando terminen de atender la petición en curso, finalicen su ejecución.

Page 4: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 4 ‐ 

 

Nota: La gestión de procesos que se pide en esta práctica está basada en la que utilizan servidores web reales como Apache.

4.1.2 Comunicación entre los procesos del servidor web En la aplicación a desarrollar existen tres casos fundamentales en los que los diferentes procesos que la componen han de comunicarse:

Los procesos trabajadores han de indicar su estado (activo o inactivo) al proceso maestro, de forma que éste pueda determinar si es necesario crear nuevos procesos trabajadores, o eliminar un exceso de procesos trabajadores inactivos. En Unix, y en el caso particular de FreeBSD, existen diferentes mecanismos de comunicación entre procesos, pero en la implementación del servidor web de esta práctica deberá utilizarse memoria compartida. Para ello, al iniciarse el servidor web, se debe crear, mediante mmap(2), una zona de memoria que será compartida por todos los procesos del servidor web. En ella se almacenará una tabla de tamaño Pmax con una entrada para cada posible proceso, que indique, además de otros campos, el estado del proceso (activo, inactivo, entrada no usada). Si el estudiante quiere usar otro mecanismo de comunicación entre procesos, debe comentarlo previamente con su profesor.

A veces, el proceso maestro ha de ordenar a los procesos trabajadores inactivos que terminen su ejecución, por ejemplo cuando hay exceso de procesos inactivos o cuando se desea finalizar la ejecución del servidor web. Para este caso, se propone que el proceso maestro envíe una señal de terminación (SIGTERM) a los procesos escogidos para su eliminación, y que éstos la capturen y finalicen ordenadamente. Si el proceso trabajador que recibe la señal está atendiendo a un cliente, terminará tras procesar la petición en curso.

Para finalizar de forma ordenada, el proceso maestro debe gestionar la captura de las señales SIGTERM y SIGINT, de forma que, cuando reciba cualquiera de ellas, dé orden a todos los procesos trabajadores para que terminen su ejecución al finalizar el procesamiento de la petición en curso, cerrando adecuadamente las comunicaciones con los clientes.

Un proceso trabajador que crea un proceso hijo para ejecutar un CGI (Common Gateway Interface) ha de pasar al CGI información sobre la invocación y recibir de éste su resultado, tal como se explica en el apartado 4.1.4. En este caso, se propone utilizar tuberías y duplicar sobre ellas los descriptores STDIN_FILENO (entrada estándar) y STDOUT_FILENO (salida estándar) del proceso CGI, además de definir las variables de entorno necesarias.

4.1.3 Parámetros del servidor web El servidor web a implementar necesita conocer algunos parámetros básicos para su correcto funcionamiento; en concreto:

Puerto TCP de escucha (opción –p[ort]). El servidor aceptará las peticiones de conexión de los clientes en el puerto TCP indicado. Este parámetro es obligatorio

Directorio base (opción –b[ase]) a partir del cual se ubican los recursos que gestiona el servidor. Por ejemplo, ~/paginas. El servidor deberá comprobar que el camino indicado existe y es un directorio. Si no es así, el servidor deberá mostrar, por su salida de error estándar, un mensaje indicándolo, y terminar su ejecución.

Page 5: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 5 ‐ 

 

Valores relacionados con el control del número de procesos trabajadores, ya comentados anteriormente: Pini (opción –Pini o –I), Pmax (opción –Pmax o -M), Pinact_min (opción –Imin o -n), y Pinact_max (opción –Imax o -m).

Ayuda (opción –h[elp]). Muestra una ayuda acerca del uso del programa, describiendo brevemente las opciones disponibles, y ejemplos de uso.

Información de depuración (opción –[debu]g). Permite elegir entre mostrar información de depuración, o no hacerlo. En el caso de usar este parámetro se puede indicar el nivel de depuración, mediante un valor numérico para elegir el nivel de detalle, siendo 1 el nivel de depuración por defecto (si se selecciona esta opción sin indicar un nivel específico). Esta opción le permitirá comprobar a su elección el funcionamiento del programa, o eliminar todos los mensajes una vez que el programa ha sido depurado completamente.

Los parámetros del servidor web se especificarán como argumentos de la línea de mandatos. No se admite que los valores estén incrustados en el código ni que sean constantes de compilación. Para facilitar el desarrollo del servidor web, se proporciona un módulo (ficheros param.c y param.h) para la gestión de los parámetros básicos de configuración del servidor, disponible en el EVA.

4.1.4 Ejecución de programas CGI CGI (Common Gateway Interface) es una interfaz estandarizada que se utiliza para que un servidor web invoque a un programa externo con el propósito generar un recurso web (documento HTML, imagen, PDF, ….) dinámicamente. Puede encontrar información más completa sobre esta interfaz en http://www.w3.org/CGI/. De manera simplificada y adaptada a las necesidades de esta práctica, la interfaz CGI consiste en lo siguiente:

El programa CGI ha de recibir por su entrada estándar el cuerpo asociado a la petición, si no es nulo (campo cuerpo de la estructura de petición descrita en el apartado 4.1.5).

El servidor web ha de recoger la salida estándar del programa CGI y enviarla tal cual al cliente.

El servidor web ha de proporcionar al programa CGI ciertos valores de contexto mediante variables de entorno. En esta práctica han de definirse las siguientes variables de entorno:

SERVER_NAME: nombre de la máquina donde se ejecuta el servidor. Se puede obtener mediante la función gethostname(3).

GATEWAY_INTERFACE: siempre tendrá el valor "CGI/1.1".

SERVER_PROTOCOL siempre tendrá el valor "HTTP/1.1".

SERVER_PORT: su valor es el número del puerto TCP en el que escucha el servidor web (en el que acepta conexiones).

REQUEST_METHOD: valdrá "GET" o "POST", dependiendo del método utilizado en esta petición (campo metodo de la estructura de petición).

SCRIPT_NAME: contendrá el nombre del programa CGI a ejecutar (campo fichero de la estructura de petición).

QUERY_STRING: contiene todo lo que va detrás del primer carácter ‘?’ del URL, si es que hay algo (campo argumentos de la estructura de petición). En caso contrario, esta variable de entorno no debe estar definida.

REMOTE_ADDR: dirección IP del cliente (campo ip_cliente de la estructura de petición).

Page 6: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 6 ‐ 

 

CONTENT_TYPE: valor del campo content_type de la estructura de petición, siempre que no sea nulo. En caso contrario, esta variable de entorno no debe estar definida.

CONTENT_LENGTH: longitud del cuerpo asociado a la petición, siempre que no sea 0 (campo long_cuerpo de la estructura de petición). En caso contrario, esta variable de entorno no debe estar definida.

Cuando el servidor web invoca al programa CGI, se crea un nuevo proceso que es el que ejecuta el programa CGI. Puesto que crear un nuevo proceso es una operación costosa (en tiempo y recursos), la utilización de programas CGI puede ser en algunos casos inviable cuando el servidor tiene muchas peticiones de CGI. Por esta razón y otras, como la facilidad de programación, es por la que se han desarrollado tecnologías de generación dinámica de documentos como PHP, JSP, ASP, .NET, JAVA, … que no necesitan usar programas CGI externos para crear documentos dinámicos.

4.1.5 API para la comunicación con los clientes web Con el fin de aislar al estudiante de la problemática de la comunicación con los clientes, se dispondrá de una serie de funciones ya codificadas y que se entregan en un fichero objeto denominado http.o (disponible en el EVA). El estudiante deberá enlazarlo con el resto de los ficheros que conformen su aplicación, para producir el ejecutable que implementará el servidor web objeto de esta práctica.

La interfaz y la documentación completa de las funciones de este módulo se encuentra en el fichero http.h (disponible en el EVA). Seguidamente se describen brevemente estas funciones:

http_crear: Devuelve una referencia a un gestor de conexiones HTTP (GestorHTTP) asociado al puerto TCP que recibe como argumento. Se habilita un puerto TCP para recibir peticiones de conexión provenientes de los procesos cliente.

http_obtener_descriptor_escucha: Obtiene el descriptor de fichero correspondiente al puerto TCP asociado a un GestorHTTP. Esta función se necesitará para alguna de las mejoras del apartado 4.3.

http_esperar_conexion: Acepta una solicitud de conexión realizada por un cliente. Esta función espera a que se conecte un cliente y, cuando esto sucede, devuelve (parámetro resultado pasado por referencia) una referencia a una ConexionHTTP (esta estructura de datos es la que permite al proceso trabajador comunicarse con el cliente).

http_obtener_ip_cliente: Obtiene la dirección IP del cliente. Dada una referencia a una ConexionHTTP, devuelve una cadena de caracteres con la dirección IP del cliente asociado.

http_obtener_descriptor_conexion: Obtiene el descriptor de la conexión con el cliente. Devuelve el descriptor de fichero usado para enviar datos al cliente, y que está asociado a la ConexionHTTP. Es probable que esta función no se necesite para esta práctica.

http_leer_peticion: Lee una petición realizada por un cliente. Dada una ConexionHTTP usada para comunicarse con un cliente, lee tanto como pueda de la misma y, si tiene suficientes datos, genera y devuelve (parámetro resultado pasado por referencia) una referencia a una Peticion. Tiene dos modos de funcionamiento seleccionables mediante el parámetro de tipo lógico bloqueante. En modo bloqueante, espera hasta recibir una petición completa. En modo no bloqueante, si no dispone de una petición completa en ese momento, retorna con la indicación HTTP_SEGUIR_ESPERANDO. En principio, para esta práctica siempre se usará el modo bloqueante, salvo que se aborden ciertas mejoras del apartado 4.3.

Page 7: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 7 ‐ 

 

http_destruir_peticion: Destruye la petición. Libera la memoria usada por la estructura de datos asociada a una Peticion.

http_enviar_respuesta: Envía la respuesta al cliente. Dada una ConexionHTTP y el descriptor de un fichero (o tubería) abierto para lectura, envía al cliente todo lo que lea a través de dicho descriptor. El parámetro es_fichero se usa para indicar si el descriptor está asociado a un fichero o no. Al enviar la respuesta de un CGI, este parámetro deberá ser 0 (ya que el descriptor usado será una tubería y no un fichero).

http_enviar_codigo: Envía un código de error al cliente. Dada una ConexionHTTP, un código de error y un mensaje explicativo (descritos en el Apéndice B), envía una respuesta de error al cliente.

http_enviar_html: Envía datos HTML. Dada una ConexionHTTP y una cadena de texto HTML, la envía al cliente a través de dicha conexión. Se puede utilizar para implementar la mejora 4.3.4.

http_cerrar_conexion: Cierra una conexión. Cierra la conexión con el cliente y libera la memoria ocupada por la ConexionHTTP.

http_destruir: Destruye el GestorHTTP. Finaliza la escucha en el puerto asociado y libera la memoria ocupada por el GestorHTTP.

La estructura de datos Peticion usada en las funciones anteriores contiene la siguiente información:

Dirección IP del cliente (campo ip_cliente).

Recurso solicitado (fichero, directorio o CGI) extraído del URL solicitado el cliente (campo fichero).

Otros campos que se utilizarán para proporcionárselos al CGI en caso de haberse solicitado un recurso de este tipo (campos argumentos, content_type, cuerpo y long_cuerpo).

Otros campos de uso interno por parte del módulo de comunicaciones (http).

4.2 Funciones básicas obligatorias El estudiante ha de desarrollar un servidor web que realice, al menos, las siguientes funciones básicas:

Recoger y procesar los parámetros de invocación del programa servidor web, descritos en el apartado 4.1.3.

Responder adecuadamente a las peticiones de documentos estáticos que realicen los clientes.

Realizar la gestión de los procesos trabajadores, tal y como se describe en el apartado 4.1.1.

Ejecutar programas externos CGI, tal y como se describe en el apartado 4.1.4

Opcionalmente, implementará las mejoras propuestas en el apartado 4.3.

4.3 Mejoras En este apartado se proponen una serie de mejoras que se pueden hacer sobre las funciones básicas del servidor web. Se valorará positivamente la implementación de las mejoras. Se recomienda que el

Page 8: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 8 ‐ 

 

estudiante explique previamente a su profesor qué mejoras ha escogido y cuál es su planteamiento para realizarlas. Las mejoras propuestas son:

4.3.1 Límite en el tiempo de ejecución de los programas CGI Si el servidor web lanza un programa CGI y éste se mete en un bucle sin fin, un interbloqueo, una espera indefinida, o cualquier otra situación similar, esto puede afectar negativamente al servidor, ya que el proceso trabajador que está esperando a que termine el CGI para devolver la respuesta al cliente también se quedará bloqueado indefinidamente y sin posibilidad de atender a otras peticiones.

Para proteger al servidor web de esta eventualidad, se puede hacer que la espera a que termine el programa CGI, por parte del proceso trabajador, esté acotada a un intervalo de tiempo que se considere suficiente para la ejecución de cualquier programa CGI correcto, por ejemplo 60 segundos. Si se supera ese límite, el proceso trabajador finaliza el programa CGI y devuelve una respuesta de error al cliente (un código de error).

4.3.2 Documento por defecto en un directorio Algunos URL no especifican el recurso que hay que descargar, sino sólo un nombre de directorio. En condiciones normales esto produciría un error, ya que no se puede devolver un directorio. Ahora bien, en estos casos, muchos servidores web buscan ciertos ficheros con nombres predeterminados en el directorio especificado y, si existen, devuelven el contenido de dichos ficheros. Los nombres de fichero predeterminado más habituales son index.html, index.htm o default.htm. En el caso de no existir estos ficheros predeterminados, podría devolver un documento HTML que contenga un listado de todos los ficheros y directorios que se encuentran en el directorio solicitado, con enlaces en sus nombres para poder descargar los recursos o explorar los directorios.

La mejora que se pide para esta práctica es únicamente la de devolver el fichero por defecto, si existe, cuando un URL no hace referencia a un recurso, sino a un directorio.

4.3.3 Inactividad de un cliente Si un cliente se conecta al servidor web y deja de enviar o recibir datos, pero sin cerrar la conexión, el proceso trabajador que lo atiende se queda bloqueado y no atiende a ningún otro cliente. Esto podría ser usado para un ataque de denegación de servicio. Para evitarlo, se puede establecer un límite de tiempo de inactividad en el cliente, pasado el cual se cierra la conexión, y el proceso trabajador vuelve a esperar la conexión de nuevos clientes.

4.3.4 Estadísticas del servidor Algunos servidores web interpretan ciertos URL como órdenes para el propio servidor. Un ejemplo es un URL como /estadisticas, que puede servir para que el servidor web genere un documento HTML con información estadística sobre el servidor. Algunos de los datos que puede proporcionar son: tiempo que lleva en marcha el servidor, tiempo de CPU consumido por todos los procesos del servidor web, memoria virtual utilizada actualmente por todos los procesos del servidor web, número de clientes y de peticiones atendidas, número de peticiones erróneas detectadas, etc. El servidor debe responder a un URL de este tipo generando un documento HTML con los datos solicitados y enviándoselo al cliente.

Page 9: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 9 ‐ 

 

4.3.5 Tratamiento de clientes abusivos Un mismo cliente puede abrir múltiples conexiones simultáneas con un servidor web. En ocasiones puede interesar que se limite la cantidad de conexiones simultáneas por cliente, para evitar que un solo cliente monopolice el servidor. Para esta mejora se propone que el servidor web tenga dos umbrales de conexiones simultáneas desde un mismo cliente. Si se alcanza el primer umbral, las conexiones posteriores se atienden, pero el proceso que las atiende reduce su prioridad. Si se alcanza el segundo umbral, no se atienden más conexiones del mismo cliente y se cierran sin más. Para esta mejora será necesario registrar las direcciones IP desde las que se conectan los clientes.

4.3.6 Mejora a propuesta del estudiante El estudiante puede proponer cualquier otra mejora que desee, siempre que guarde relación con los objetivos principales de la práctica. En este caso obligatoriamente ha de discutirla previamente con el profesor y obtener su visto bueno.

4.4 Pruebas del servidor Web A continuación se comentan algunas de las pruebas que los estudiantes pueden realizar para comprobar el funcionamiento de su servidor web. No obstante, se recuerda que las pruebas pueden servir para poner de manifiesto errores, pero nunca para demostrar la corrección del programa. Es fundamental hacer un diseño meditado y una codificación cuidadosa para lograr que un programa funcione correctamente.

4.4.1 Acceso desde un navegador de la máquina anfitriona La prueba más evidente consiste en acceder al servidor web desarrollado por el estudiante usando un navegador web normal y corriente, como pueda ser Firefox, Google Chrome, Internet Explorer, etc. Para ello, habrá que especificar un URL de la forma: http://XXX.XXX.XXX.XXX:PUERTO/RECURSO donde XXX.XXX.XXX.XXX es la dirección IP de la interfaz em0 de la máquina virtual donde está corriendo el servidor, PUERTO es el puerto de escucha TCP usado al arrancar el servidor1 y RECURSO es el recurso que se desea visualizar o descargar.

Por ejemplo, si la IP de su máquina es 192.168.203.131, se decide usar el puerto 50.000, y se quiere mostrar los recursos que hay en el directorio /usr/share/doc/ntp de la máquina, ejecute el servidor web con este mandato: ./servidorWeb -p 50000 -b /usr/share/doc/ntp. Y en un navegador puede visualizar los recursos mediante el url: http://192.168.203.131:50000/index.html

1 Es conveniente no elegir un puerto que ya esté usando otro programa, por ello se aconseja usar números mayores de 50.000

Page 10: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 10 ‐ 

 

Ilustración 1.‐ Recurso index.html del directorio  /usr/share/doc/ntp 

Para facilitar la realización de pruebas completas se ha preparado un conjunto de recursos web y programas CGI de ejemplo que puede ser utilizado directamente por los estudiantes. Estos recursos se encuentran disponibles a través del EVA en el fichero pruebas.tgz. Para probar su servidor con los recursos de prueba, puede copiar el fichero pruebas.tgz a un directorio de su elección (por ejemplo ~/bimestre1), y ejecutar el mandato tar xzpf pruebas.tgz. Con ello se creará la estructura de directorios y ficheros necesaria para las pruebas, con sus permisos adecuados. Para probar estos recursos, arranque su servidor web usando el siguiente mandato: ./servidorWeb -p 50000 -b ~/bimestre1/paginas Y para visualizar los documentos desde un navegador, use este URL: http://192.168.203.131:50000/index.html (suponiendo que la dirección IP de su máquina es 192.168.203.131):

Page 11: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 11 ‐ 

 

Ilustración 2.‐ Recurso index.html al mostrar las páginas de prueba 

Por si está interesado, puede encontrar el código fuente de los programas CGI de ejemplo en el EVA (en el fichero fuentes-cgi.tgz).

Tenga en cuenta que si está usando un navegador que tenga configurado un servidor Proxy, deberá deshabilitarlo para conectarse a su servidor web.

4.4.2 Programa ejemplo.c En el EVA encontrará el fichero ejemplo.c que le puede servir como base para comenzar la codificación de la práctica. Este ejemplo implementa un servidor web monoproceso que atiende una petición de un cliente y finaliza. Una vez compilado puede ejecutarlo de la siguiente forma:

./ejemplo -p 50000 -b

Y a continuación, desde un navegador, solicitar el url:

http://192.168.203.131:50000/basica.htm Todo ello suponiendo que la dirección IP de la máquina en la que está ejecutando su servidor web es 192.168.203.131, y que existe el fichero basica.htm en el directorio ~/bimestre1/paginas.

El documento Ejemplo.pdf, que puede encontrar en el EVA, describe paso a paso cómo se ha construido el código de este programa.

4.4.3 Utilización del programa de descarga de recursos wget El programa wget permite descargar recursos web y guardarlos en ficheros. Se usa con frecuencia para obtener copias locales de documentos HTML y para automatizar accesos a aplicaciones web.

Page 12: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 12 ‐ 

 

Es otra posibilidad más para realizar pruebas con el servidor web de esta práctica, ya que permite descargar recursos individuales, mientras que un navegador intentará descargar también posibles referencias dentro del documento HTML, como imágenes, etc. Además, proporciona alguna información un poco más detallada sobre el resultado de la operación.

Para ejecutar wget basta con invocarlo (desde una sesión en la máquina FreeBSD) mediante un mandato similar al siguiente:

wget –O fichero_destino http://localhost:PUERTO/recurso

En el mandato anterior, fichero_destino es el fichero donde se quiere guardar el recurso descargado. Si no se quiere ese recurso para nada, puede especificarse /dev/null para descartarlo. El programa wget tiene muchas opciones que permiten hacer multitud de pruebas con un servidor web, por lo que se recomienda al estudiante que consulte su página de manual.

Si wget no está instalado en su máquina, podrá instalarlo ejecutando el mandato pkg_add –r wget como superusuario. Para más información sobre la instalación de paquetes de software en FreeBSD, consulte el manual en línea de FreeBSD. Recuerde que si la máquina en la que quiere instalar el nuevo paquete necesita conectarse a Internet a través de un servidor Proxy, deberá configurarlo adecuadamente.

4.4.4 Pruebas de carga Las pruebas interactivas con un navegador web no van a producir suficiente carga de trabajo al servidor web como para comprobar su respuesta frente a una alta intensidad de peticiones. Para generar una mayor carga de trabajo ha de utilizarse un programa especial, como puede ser http_load. Este programa también se puede descargar e instalar en su máquina FreeBSD mediante el mandato pkg_add –r http_load. Para la instalación, tenga en cuenta la configuración de PROXY como se indica en el apartado 4.4.3.

El programa http_load es capaz de generar una carga arbitraria de peticiones HTTP a un servidor web. El estudiante puede consultar su página de manual para obtener más detalles, pero en esencia se le puede indicar a http_load que haga peticiones a una cierta tasa de peticiones/segundo o también que mantenga un ritmo sostenido de una cierta cantidad de peticiones en paralelo. Las peticiones que hace http_load se escogen aleatoriamente de entre los URL contenidos en un fichero.

Una forma rápida de generar un fichero en el directorio ~/bimestre1 con todos los URL de los documentos estáticos de prueba contenidos en el manual de ntp es la siguiente:

cd /usr/share/doc/ntp find . –type f –print | awk '{ print "http://localhost:PUERTO/" $0 }' > ~/bimestre1/lista-urls.txt

A continuación se podría usar http_load de alguna de las dos maneras siguientes:

http_load –checksum –rate 15 –seconds 10 ~/bimestre1/lista-urls.txt http_load –checksum –parallel 15 –seconds 10 ~/bimestre1/lista-urls.txt

La primera orden especifica una carga de 15 peticiones/segundo durante un total de 10 segundos. La segunda orden especifica que se mantenga una carga de 15 peticiones en paralelo durante un total de 10 segundos. No olvide ejecutar el servidor con la opción -b /usr/share/doc/ntp.

Page 13: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 13 ‐ 

 

4.4.5 Programa servidor web de prueba En el EVA encontrará la implementación de un servidor web, similar al que se le pide en esta práctica, que puede usar para hacerse una idea de las funcionalidades que debe soportar su servidor. Su nombre es servidorWeb.

Para probarlo, puede copiarlo a su máquina y ejecutarlo con las opciones especificadas en este enunciado. Ante cualquier duda, puede invocarlo con la opción –h para obtener información acerca de su funcionamiento. Recuerde comprobar que el programa servidorWeb de ejemplo tenga permiso de ejecución después de copiarlo a su máquina.

4.4.6 Programa verificador del servidor web En el EVA encontrará un programa llamado verificador, que ejecuta una amplia batería de pruebas sobre el servidor web. Esto le resultará de mucha ayuda para detectar posibles fallos o deficiencias de implementación en su servidor web.

Para saber cómo utilizar el programa verificador, ejecútelo sin más y siga las indicaciones mostradas en pantalla. Debe ejecutar este programa en la misma máquina que el servidor web cuyo funcionamiento quiere verificar. No olvide comprobar que el verificador tiene permiso de ejecución después de copiarlo a su máquina. Tenga en cuenta también que este programa usa wget con lo cual debe haber instalado esta aplicación previamente tal y como se indica en el apartado 4.4.3.

El programa verificador, antes de empezar a hacer las pruebas, comprueba varias cosas necesarias y, si alguna no se cumple, se detiene (salvo que hayan puesto la opción -s) y avisa al usuario. Las comprobaciones que realiza, entre otras, son:

Que no haya procesos servidorWeb en ejecución (que serían de pruebas anteriores y pueden confundir al verificador).

Que existan diversos ficheros en el directorio de las páginas que luego va a usar en las pruebas y que tengan los permisos esperados en cada caso.

Que esté instalado el programa wget.

4.4.7 Programa comprobador de las entregas En el EVA encontrará un programa llamado comprobar-entrega, que comprueba que el fichero a subir al EVA cumple con los requisitos de la entrega, para que pueda validarlo antes de subirlo.

5 Fases de realización de la práctica Se recomienda al estudiante ser constante en la realización de esta práctica y que reparta el trabajo adecuadamente. Para ello, se propone una separación de la práctica en fases, a título orientativo.

Si el estudiante diseña y estructura adecuadamente su programa, el paso de una fase a la siguiente apenas requerirá modificaciones en lo ya completado, y únicamente habrá que añadir las nuevas funcionalidades. Se recomienda consultar los sucesivos diseños con el profesor de laboratorio.

5.1 Fase 1. Duración: de una a dos semanas Durante la primera fase, el estudiante debe desarrollar un servidor web monoproceso que solamente sea capaz de servir ficheros estáticos. Esto le servirá para tomar contacto con la práctica y para

Page 14: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 14 ‐ 

 

asegurarse de que sabe manejar adecuadamente la API de comunicaciones HTTP con los clientes. Evidentemente, este servidor no será capaz de atender más que una conexión en cada momento.

Además, debe realizar el procesamiento completo de los parámetros de configuración del servidor, e incluir la gestión de las señales SIGTERM y SIGINT para poder terminar ordenadamente la ejecución del servidor web.

A continuación se muestra un seudocódigo orientativo para la resolución de esta fase:

Procesar los parámetros de configuración Establecer las rutinas de tratamiento de las señales Crear gestorHTTP ( in puerto ) -> GestorHTTP Repetir

Esperar conexión de cliente ( in gestorHTTP, out cliente ) Leer petición ( in cliente, out petición ) Procesar documento estático ( in cliente, in petición ) Destruir petición ( in petición ) Cerrar conexión ( in cliente ) Hasta final de programa Destruir gestorHTTP ( in GestorHTTP ) Procesar documento estático ( in cliente, in petición ): fich = Abrir fichero ( in petición->fichero ) Si fich == -1 /* Error al abrir el fichero */ Enviar código de error ( in cliente, in 401|402|403… ) Si no Enviar respuesta ( in cliente, in petición, in fich ) Cerrar fichero ( in fich ) Fin si

El seudocódigo anterior cierra la conexión con el cliente tras servir una sola petición. Esto no es muy eficiente, ya que obliga a abrir una conexión nueva por cada recurso que haya que descargar, y muchos documentos pueden desencadenar la solicitud de decenas o incluso cientos de recursos adicionales. No obstante, será suficiente para esta primera fase puesto que, al tratarse por el momento de un servidor monoproceso, es incapaz de manejar varias conexiones en paralelo. Hay que tener en cuenta que algunos agentes de usuario abren varias conexiones simultáneas para descargar en paralelo los recursos de un solo documento. Si el servidor sólo es capaz de manejar una conexión en cada momento y no la cierra después de atender una única petición, esos agentes de usuario no serían capaces de descargar completamente los documentos. En el momento en el que se pase al servidor multiproceso, se modificará el seudocódigo anterior para procesar más de una petición en cada conexión.

Obsérvese que, por simplicidad, ni en el seudocódigo propuesto para esta fase ni en los de las demás fases se explicita en profundidad el tratamiento de los diversos errores y situaciones excepcionales que pueden producirse durante la ejecución del programa. No obstante, en su programa, el estudiante debe detectar y tratar adecuadamente todos esos errores y situaciones excepcionales.

En este seudocódigo, el proceso permanece en un bucle hasta final de programa. Ese final de programa se producirá cuando el proceso reciba la señal SIGTERM o la señal SIGINT. El manejador asociado a estas señales deberá modificar la variable de control de dicho bucle. Tenga en cuenta que, si se recibe una señal mientras las funciones http_esperar_conexion() o http_leer_peticion() están bloqueadas a la espera de recibir una solicitud de conexión o de leer una petición, estas funciones retornarán inmediatamente con el código HTTP_ESPERA_INTERRUMPIDA. Obviamente, en este caso no habrá cliente que atender ni petición que procesar.

Page 15: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 15 ‐ 

 

Para probar esta fase se recomienda que el estudiante pruebe a solicitar el recurso basica.htm del directorio páginas.

Ilustración 3.‐ Recurso basica.html de las páginas de prueba 

Documentación a presentar: Código fuente del programa.

5.2 Fase 2. Duración: de una a dos semanas En la segunda fase, se puede añadir la capacidad de ejecutar programas CGI al servidor realizado en la fase anterior, manteniéndolo aún como un servidor con un sólo proceso maestro (más el proceso hijo que ejecute el programa CGI). De esta forma, se aprenderá a crear nuevos procesos para ejecutar programas externos, a duplicar descriptores y redirigir la entrada/salida, y a manipular variables de entorno.

A continuación se muestra un seudocódigo orientativo para la resolución de esta fase, resaltando en negrita las modificaciones con respecto al seudocódigo propuesto para la fase anterior:

Procesar los parámetros de configuración Establecer las rutinas de tratamiento de las señales Crear gestorHTTP ( in puerto ) -> GestorHTTP Repetir

Esperar conexión de cliente ( in gestorHTTP, out cliente ) Leer petición ( in cliente, out petición ) Si petición es CGI Procesar CGI ( in cliente, in petición ) Si no Procesar documento estático ( in cliente, in petición ) Fin si Destruir petición ( in petición ) Cerrar conexión ( in cliente ) Hasta final de programa Destruir gestorHTTP ( in GestorHTTP )

Procesar_CGI ( in cliente, in petición ): Crear tubería_p-h /* para enviar información del padre al hijo */ Crear tubería_h-p /* para enviar información del hijo al padre */ Switch ( fork() ) Case Padre: Si petición->cuerpo no es nulo

Page 16: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 16 ‐ 

 

Escribir cuerpo en tubería_p-h Fin si Cerrar tubería_p-h Enviar respuesta ( in cliente, in petición, in tubería_h-p) Esperar la terminación del programa CGI Case Hijo: Establecer variables de entorno Redirigir su entrada estándar a la tubería_p-h Redirigir su salida estándar a la tubería_h-p Ejecutar programa CGI Si llega aquí, enviar código de error al cliente y terminar End Switch

Para que las tuberías funcionen correctamente, tanto el proceso padre como el proceso hijo deben cerrar los extremos de las tuberías que no usan para nada. Esto no ha sido incluido en el seudocódigo anterior. Además, una vez que las tuberías han cumplido su función, deben cerrarse todos sus descriptores asociados, puesto que en caso contrario el servidor podría quedarse sin descriptores para poder abrir nuevos ficheros o tuberías, con lo que no podría seguir atendiendo peticiones. Será labor del estudiante determinar en qué puntos de su programa hay que realizar estas operaciones.

Para probar esta fase se recomienda que el estudiante abra los recursos de tipo CGI accesibles a partir del recurso CGIs.html del directorio de páginas proporcionado.

Ilustración 4.‐ Resultado obtenido tras pulsar el enlace CGI básico en el recurso CGIs.htm 

Page 17: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 17 ‐ 

 

Ilustración 5.‐ Resultado obtenido tras pulsar el enlace CGI que muestra las variables de entorno en el recurso CGIs.htm 

Documentación a presentar: Código fuente del programa.

5.3 Fase 3. Duración: dos semanas En la tercera fase, se convertirá el programa en un servidor multiproceso que satisfaga todos los requisitos básicos indicados en el apartado 4.2. En esencia, el servidor tendrá dos secuencias de ejecución diferentes: por un lado estará el código que ejecutan los procesos trabajadores, que básicamente coincidirá con lo realizado en las fases anteriores (salvo que ya no se cerrará la conexión con el cliente tras procesar una sola petición, sino cuando lo decida el cliente), y por otro lado aparecerá como novedad la tarea de vigilancia de los trabajadores, que la realizará el proceso maestro. Además, será necesario introducir una estructura de datos en memoria compartida que sirva para que los procesos trabajadores comuniquen su estado al proceso maestro. Cuando el maestro crea los trabajadores, los crea en el estado INACTIVO. Los trabajadores pasarán al estado ACTIVO cuando tengan establecida una conexión con un cliente, y volverán al estado INACTIVO cuando el cliente cierre la conexión. Cuando el maestro reciba la señal de terminación de los trabajadores y constate su finalización, marcará la entrada correspondiente de la tabla de trabajadores como NOUSADO.

A continuación se muestra un seudocódigo orientativo del programa principal, que crea los procesos trabajadores, y a continuación se comporta como proceso maestro:

Procesar los parámetros de configuración Establecer las rutinas de tratamiento de las señales (además SIGCHLD) Crear gestorHTTP ( in puerto ) -> GestorHTTP Crear tabla de trabajadores en memoria compartida Marcar todas las posiciones de la tabla de trabajadores como NOUSADO Crear Pini trabajadores Repetir Sleep(1) Contar trabajadores inactivos /* en estado INACTIVO */ Si cuenta > Pinact_max

Page 18: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 18 ‐ 

 

Enviar SIGTERM a (cuenta – Pinact_max) trabajadores inactivos Si no Si cuenta < Pinact_min Crear (Pinact_min – cuenta) trabajadores, respetando el límite Pmax Fin si Hasta final de programa Enviar a todos los trabajadores la señal de terminación Esperar a que todos los trabajadores hayan terminado su ejecución Destruir gestorHTTP ( in GestorHTTP )

El seudocódigo orientativo para los trabajadores sería el presentado a continuación. Es análogo al ya desarrollado para la fase anterior, aunque se ha modificado para procesar más de una petición en una misma conexión y para actualizar el estado del trabajador en la tabla compartida con el proceso maestro. No se ha considerado el control de los errores que pueden generar las funciones del módulo http, para simplificar los algoritmos. En negrita se resaltan las novedades:

Ajustar los manejadores de las señales Repetir Esperar conexión de cliente ( in gestorHTTP, out cliente )

Marcar mi posición en la tabla de trabajadores como ACTIVO Repetir

Leer petición ( in cliente, out petición ) Si petición es CGI Procesar_CGI(in cliente, in petición) Si no Procesar documento estático ( in cliente, in petición ) Fin si Destruir petición ( in petición ) Hasta que el cliente se desconecte o me ordenen terminar

Marcar mi posición en la tabla de trabajadores como INACTIVO Cerrar conexión ( in cliente ) Hasta que me ordenen terminar

El ajuste de los manejadores de las señales puede ser necesario porque el proceso trabajador heredará los ajustes del maestro y éstos podrían no ser los adecuados para el trabajador. En concreto:

El trabajador no tiene que procesar SIGINT, ya que eso lo hace el maestro.

La respuesta a SIGTERM también es diferente, ya que el maestro tiene que pedir a todos los trabajadores que terminen, mientras que el trabajador tiene que terminar su ejecución tras procesar la petición actual (si la hubiere). Ahora bien, el manejador de la señal en sí podría ser el mismo si lo único que hace es cambiar el valor de la variable de control del bucle principal del proceso.

El procesamiento de SIGCHLD también es diferente, puesto que en el maestro hay que marcar que el trabajador que ha terminado ya no existe, mientras que en el trabajador esta señal sólo se recibe cuando termina un proceso hijo que se ha creado para ejecutar un CGI.

Téngase en cuenta que, para indicar a un trabajador que debe finalizar su ejecución, el proceso padre le envía la señal SIGTERM. El trabajador, al recibirla, tomará nota de que debe terminar su ejecución cuando concluya el procesamiento de la petición actual.

Además, hay que determinar cómo se actualiza la tabla de trabajadores para reflejar la creación y la terminación del proceso trabajador. El paso de NOUSADO a INACTIVO lo podría hacer el proceso trabajador cuando comienza su ejecución, pero eso puede generar condiciones de carrera con el maestro. Por tanto, es conveniente que el maestro lo marque como INACTIVO justo antes de crearlo.

Page 19: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 19 ‐ 

 

Si por alguna razón, la creación del trabajador fallara, el maestro debería volver a marcarlo como NOUSADO. El paso de INACTIVO a NOUSADO podría hacerlo el trabajador justo antes de terminar, o el proceso padre cuando recibe la señal SIGCHLD que le indica que un hijo ha terminado. Se recomienda que sea el maestro el que lo haga (así también se marcarían como no usadas las posiciones de los trabajadores que mueran abruptamente por cualquier motivo).

El maestro necesita conocer el PID de los procesos trabajadores para poder mandarles la señal de terminación. Hay que tener en cuenta posibles condiciones de carrera si un trabajador termina prematuramente (antes de que se haya anotado su PID). Si el maestro recibe la señal SIGCHLD de un trabajador y trata de localizar la entrada correspondiente de la tabla de trabajadores para marcarla como NOUSADO, podría no encontrarla (porque aún no se haya anotado su PID). Por tanto, habrá que garantizar que esto no ocurre. Una posibilidad es evitar que se procese la señal SIGCHLD hasta que el PID del nuevo trabajador haya sido anotado (usando sigprocmask(2)).

Se recomienda que los trabajadores ignoren la señal de terminación de los procesos que ejecutan los programas CGI, y que sincronicen con ellos directamente, antes de pasar a atender una nueva petición. De esta forma, pueden detectar fallos en la ejecución de los CGI, para avisar al cliente en esos casos.

Cuando el maestro se entera de que le ha llegado la señal SIGCHLD y pasa a ejecutar la rutina de atención correspondiente, puede ser que hayan terminado varios procesos hijos antes de que se ejecute su rutina de atención, por lo que deberá sincronizar con todos los hijos que estén pendientes de sincronizar, para evitar que se queden zombis, y para anotar correctamente su estado en la tabla.

Obsérvese que en esta fase ya no hay problemas con los agentes de usuario que abren múltiples conexiones simultáneas con el servidor, ya que el servidor es capaz de atender varias conexiones a la vez, usando, para ello, varios trabajadores en paralelo. NOTA: si el número máximo de procesos trabajadores es demasiado bajo (menos de 4), sí podría haber problemas con esos agentes de usuario. Por ejemplo, podría verse que, al abrir un documento web con muchas imágenes en un navegador web, se cargan rápidamente algunas imágenes, mientras que otras tardan mucho más en cargarse.

5.4 Fase 4. Duración: una semana Esta fase final es opcional y se tendrá en cuenta para la calificación de la práctica. El estudiante ha de escoger una o varias de las mejoras propuestas en el apartado 4.3, e implementarla en su servidor web. Se recomienda que haga una valoración previa de lo que cada una de ellas podría suponer, a fin de escoger la que le resulte más interesante y más conveniente de realizar. También se puede proponer al profesor alguna mejora no recogida en este documento.

Documentación a presentar: Código fuente del programa junto con un documento que indique qué mejora opcional se ha realizado.

Page 20: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 20 ‐ 

 

Apéndice A : Introducción a las tecnologías web En su forma más sencilla, un servidor web es una aplicación que permite descargar recursos mediante el protocolo HTTP. La mayoría de esos recursos son documentos en formato HTML que describen la información a presentar al usuario final, por lo general estos documentos contienen referencias a otros tipos de recursos como imágenes, vídeo, hojas de estilo, documentos en lenguaje de script, documentos PDF, etc., que también se pueden descargar del servidor web. Por lo general, los documentos HTML en cuestión han sido generados de antemano mediante un programa de edición de páginas web, o son generados dinámicamente mediante un generador de contenidos u otro tipo de generación de contenidos dinámicos, y los recursos referenciados se han almacenado en algún directorio de la máquina donde se ejecuta el servidor web.

Normalmente, los navegadores web descargan primero el documento que contiene la descripción de la página en HTML, lo interpretan y, si en él figuran referencias a otros recursos, entonces los descargan del servidor web. Finalmente, componen con todo ello la imagen que aparece en la pantalla del cliente. Como es bien sabido, en los documentos HTML también pueden aparecer referencias a otros recursos que no son descargados automáticamente sino que se encuentran accesibles a través de mecanismos de navegación (hiperenlaces o hipervínculos). Estos mecanismos desencadenarán una petición sobre el servidor correspondiente si el usuario hace clic sobre el hiperenlace en cuestión.

Por ejemplo, si un usuario utiliza un navegador web para solicitar un recurso con URL http://www.w3c.es/index.html, el navegador se conecta a la máquina www.w3.org y, mediante el protocolo HTTP, le pide el fichero /index.html. El servidor web comprueba si existe dicho documento en su directorio raíz y, en caso afirmativo, se lo transmite al cliente como respuesta a su petición. En caso negativo, envía un código de error.

Si en el documento anterior figuran referencias a imágenes, por ejemplo a /img/2010/logo-w3c-mobile-lg, el navegador, seguidamente, pide al servidor web el documento correspondiente, para situarlo en la posición adecuada de la página.

A veces, el servidor web procesa de manera especial algunos URL que no corresponden a ficheros existentes. Por ejemplo, si el cliente solicita abrir el URL http://www.w3c.es/Consorcio y resulta que Consorcio es un directorio y no un recurso, el servidor web asume que el cliente está solicitando el fichero por defecto index.html que haya en ese directorio, es decir, /Consorcio/index.html.

Lo que se ha explicado anteriormente corresponde a los denominados documentos estáticos. Existen URL que apuntan a lo que se denominan documentos dinámicos o CGI, es decir, no apuntan explícita o implícitamente a un documento existente, sino que hacen que el servidor ejecute un programa externo que genera, por su salida estándar, unos datos que han de llegar al cliente. Lógicamente el documento que genera se corresponde con un recurso web, por lo que el cliente visualizará, reproducirá o descargará dicho recurso sin apreciar ninguna diferencia por el hecho de que éste haya sido generado por un programa. Como a cualquier programa, a un CGI se le pueden pasar diferentes argumentos para que personalice el recurso generado. Por ejemplo, si un cliente solicita el URL http://www.utpl.edu.ec/cgi/calificaciones?cedula=12345678&materia=232, el servidor web ejecuta el programa calificaciones, pasándole un argumento de nombre cedula con el valor 12345678 y otro argumento de nombre materia con el valor 23. Se supone que el programa hará algo con dichos argumentos (en este caso, quizá busque en una base de datos la calificación del

2 Este URL es sólo un ejemplo, no se encuentra disponible.

Page 21: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 21 ‐ 

 

estudiante cuyo número de cédula es 12345678 en la materia cuyo código es el 23) y finalmente generará un documento con la información resultante en formato HTML, la cual se enviará como respuesta al cliente. Este documento dinámico podría hacer referencia a otros recursos gráficos, de audio, etc., los cuales descargaría el cliente en cuanto interpretara el documento HTML. Existen dos métodos alternativos de invocar a los programas CGI, llamados GET y POST.

Existen otras muchas tecnologías que permiten generar recursos dinámicos, como PHP, JSP, ASP, .NET, JAVA, etc., que simplemente se mencionan a título informativo, ya que no se van a tener en cuenta en esta práctica.

Los recursos dinámicos son muy útiles en combinación con los formularios. Un formulario es un elemento que puede aparecer en un documento HTML y que describe diversos elementos de entrada que el usuario puede completar, como cajas de texto, listas desplegables, botones de radio, etc. Así mismo, el formulario puede proporcionar algún elemento de acción (botón, imagen, etc.) que, al ser pulsado por el usuario, hace que el navegador envíe a un determinado URL del servidor los valores introducidos o seleccionados en el formulario como argumentos de la petición. Ese URL deberá ser un programa CGI, que recogerá los argumentos enviados para procesarlos y generar un recurso como respuesta al cliente.

El URL http://www.utpl.edu.ec/cgi/calificaciones?cedula=12345678&materia=23, usado como ejemplo anteriormente, podría haberse generado cuando el usuario ha pulsado el botón de enviar de un formulario que contenía una caja de texto llamada cédula en la que había introducido la cadena 12345678 y una lista desplegable en la que había seleccionado la materia Arquitectura y Computación Paralela, cuyo código numérico resulta ser el 23. Los clientes web envían sus peticiones y reciben sus respuestas por medio del protocolo HTTP, cuya versión más reciente, HTTP/1.1, se encuentra especificada en la RFC 2616. A grandes rasgos, un cliente abre una conexión TCP con el servidor web y entonces entra en un bucle de envío de una petición (generalmente el método GET) y recepción de una respuesta. Este bucle se repite hasta que, bien el cliente, o bien el servidor, deciden cerrar la conexión. Obsérvese que, a través de una misma conexión, el cliente no envía una nueva petición hasta haber recibido la respuesta de la petición en curso. Obsérvese, también, que un agente de usuario, podría crear varios clientes para abrir varias conexiones simultáneas con el servidor con el fin de hacer varias peticiones en paralelo.

Page 22: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 22 ‐ 

 

Apéndice B : Códigos de error En el protocolo HTTP, toda respuesta de un servidor web debe incluir un código de estado que indica el resultado de la solicitud HTTP del cliente, descritos en la RFC 2616 del protocolo HTTP. De manera resumida, el código puede ser de éxito (código 200) o de error (códigos 4XX y 5XX).

El estudiante no debe preocuparse de enviar el código de éxito (código 200) en las peticiones satisfactorias, puesto que ya lo hace automáticamente la biblioteca de funciones suministrada. En cambio, cuando el servidor web del estudiante detecte algún problema que impida responder satisfactoriamente a una petición, debe responderse con un código de estado apropiado usando la función http_enviar_codigo de la biblioteca de funciones suministrada.

En este apéndice únicamente se tratarán los principales códigos de estado correspondientes a problemas que tiene el servidor web para atender una solicitud realizada por un cliente, y que son suficientes para realizar la práctica. Cuando se da esta situación, el servidor debe enviar al cliente un código de error numérico, un mensaje y, opcionalmente, una página web con información de la causa del error.

Los códigos de error más comunes, junto con un posible mensaje explicativo son:

400 Bad Request. El servidor web no pudo entender la solicitud debido a errores de sintaxis en la petición.

403 Forbidden. El servidor entendió la solicitud pero no la va a atender. Un caso típico de este error sería cuando el URL solicitado corresponde a un directorio y no a un recurso, en ese directorio no se encuentra la página por defecto y el servidor no permite listar directorios. También puede deberse a que se ha solicitado un recurso para el que no se tiene permiso de lectura.

404 Not Found. El servidor no ha encontrado el recurso correspondiente al URL solicitado. Este error puede deberse a un error de ortografía o de sintaxis en el URL o que se trate de un recurso que ya no existe en el servidor.

405 Method Not Allowed. El método especificado en la solicitud no se permite para el recurso solicitado. Este error ocurre por ejemplo cuando se hace una petición POST y el servidor web solamente permite peticiones GET para el tipo de archivo correspondiente al URL solicitado.

408 Request Timeout. El servidor recibió una solicitud de conexión de un cliente, pero éste no llegó a enviar una petición en el tiempo que el servidor esperaba.

500 Internal error. Ocurrió un problema no especificado en el servidor, como falta de memoria, estructuras de datos corruptas, etc.

Page 23: Aplicacion Multiproceso

Arquitectura y Computación Paralela    Curso 2014/2015

   

 Práctica 3 – página 23 ‐ 

 

Apéndice C : Principales páginas de manual de interés A continuación se enuncian algunas de las páginas de manual de FreeBSD más relevantes que el estudiante tendrá que consultar para realizar la práctica. Para más información sobre ellas, consúltese la correspondiente página de manual y la información proporcionada en clase.

Páginas de manual para las funciones obligatorias:

fork(2): crea un proceso nuevo. exec(3): familia de funciones que permiten ejecutar programas. exit(3): finaliza un proceso. _exit(2): finaliza un proceso. kill(2), killpg(2): envían una señal a un proceso o a un grupo de procesos. signal(3): captura una señal. sigaction(2): examinar y modificar las acciones a realizar al recibir una señal. sigprocmask(2): examinar y modificar las señales bloqueadas. sigsuspend(2): espera inactiva hasta que se reciba una señal. sigemptyset(3), sigfillset(3), sigaddset(3), sigdelset(3), sigismember(3):

funciones POSIX para manipular conjuntos de señales. mmap(2): crea zonas de memoria virtual compartida. open(2): abre un fichero. read(2), write(2): lee o escribe en un descriptor de E/S. close(2): cierra un descriptor de E/S. pipe(2): crea una tubería. dup(2), dup2(2): duplican un descriptor de E/S. Se suelen utilizar para redireccionar la

entrada o la salida de un proceso. wait(2), waitpid(2), wait4(2), wait3(2): familia de llamadas al sistema para esperar

y recoger información sobre los procesos hijos que han finalizado. sleep(3): detiene un proceso durante el tiempo especificado. getenv(3), setenv(3): permiten consultar y modificar variables de entorno. gethostname(3): permite obtener el nombre de la máquina en la que se ejecuta el programa. getopt(3), getopt_long(3): analizan los argumentos de invocación de un programa. errno(2): variable en la que las llamadas y funciones del sistema devuelven un código

explicativo en caso de error. stat(2), fstat(2): obtienen información sobre los atributos de un fichero.

Páginas de manual para las mejoras:

getpriority(2), setpriority(2): obtienen o cambian la prioridad de un proceso. getrusage(2): devuelve información sobre los recursos consumidos por un proceso. select (2): permite que un proceso de usuario solicite al kernel la espera de algunos

eventos determinados, reanudándose la ejecución de dicho proceso únicamente cuando se produzca alguno de ellos.

setitimer(2), alarm(3): pone en marcha un temporizador.

El módulo http que se proporciona, ya codificado, al estudiante para gestionar las comunicaciones con los clientes también hace uso de otras llamadas al sistema como, por ejemplo, socket(2), bind(2), listen(2), accept(2), recv(2), send(2), setsockopt(2), fcntl(2) y shutdown(2).