Skip to content

Indicaciones sobre el Diseño de la práctica 2

armando-ferro edited this page Feb 20, 2018 · 1 revision

El desarrollo de la práctica en todo su enunciado dependerá del interés del alumno y del trabajo adicional que pueda realizar fuera de las horas regladas de laboratorio. Esta guía está más enfocada a proponer una metodología sencilla de trabajo en laboratorio que pueda servir para formar suficientemente al alumno para conseguir sus objetivos. La secuencia de pasos a realizar en el tiempo de laboratorio es la siguiente:

  1. Pensar bien en la reutilización del código que se está desarrollando pues si el código que se realiza es suficientemente flexible, los únicos cambios que hay de un programa a otro afectan sólo al tipo de recurso de comunicaciones que se usa. La lógica de cada programa es similar. Es una buena ocasión para aprender a usar las instrucciones de preprocesamiento, saber generalizar funciones, crear librerías y utilizar makefiles.
  2. El primer caso de pipes es un poco especial y se puede hacer aprovechando la creación de jerarquía de procesos de la práctica anterior. Lo más delicado es saber crear y usar de forma adecuada el recurso de pipe generado con la primitiva pipe(). Es un recurso con dos descriptores de dispositivo que tiene un funcionamiento peculiar. Hay infinidad de ejemplos en internet sobre su uso. Pensar en dónde debe crearse el recurso pipe dentro de la jerarquía para que los procesos que se quieran comunicar sepan acceder correctamente al recurso.
  3. Los demás ejercicios se pueden hacer con una estructura de programa similar tanto para el cliente como para el servidor. Son dos programas diferentes pero ambos deben de identificar el recurso común de comunicaciones. En UNIX es común acceder a los recursos externos como si fuesen dispositivos. Eso es aplicable también a los ficheros. Eso permite que las aplicaciones de UNIX puedan fácilmente comunicarse. Un consejo es que creéis en vuestros programas funciones suficientemente genéricas tanto para recibir datos como para enviarlos que puedan personalizarse para cada caso según usemos un recurso u otro.
  4. En el caso de named-pipes, el recurso a usar es un recurso externo que debe existir en el sistema de ficheros. Hay dos opciones: (a) crearlo desde programa (mkfifo()), o (b) crearlo desde el sistema (comando mknod). Aparece como si fuese un fichero pero realmente es un dispositivo especial. Con ls –l podéis verlo y el sistema os dará información de que tipo de dispositivo es. Cuidado con los permisos.
  5. La forma de trabajo con un dispositivo named-pipe es similar a como se hace con dispositivos o ficheros; usando las primitivas open(), write(), read(), close(). Si revisáis el manual de open() (man 2 open) veréis que opera de una forma especial con dispositivos de este tipo para sincronizar los procesos. Por ejemplo si un proceso intenta abrir el recurso para leer, el sistema lo retiene hasta que no haya otro proceso que abra ese recurso para escribir. Como esto muchas cosas más que podéis aprender leyéndoos las páginas de manual de las funciones que usáis.
  6. En el caso de las colas de mensajes, la creación del recurso se debe hacer desde la aplicación a través de las primitivas msgget() con las claves y permisos adecuados. El envío de mensajes y recepción se hace con primitivas específicas como msgsnd() y msgrcv(). SI creáis bien la cola de mensajes la podéis ver a través del comando ipcs.
  7. Un primer problema lo tenéis a la hora de identificar el recurso que queréis usar. Se utiliza una clave que se supone que es única y que nadie que no sea vuestra aplicación va a utilizar la misma clave. Para ello conviene que elijáis una clave única. Estas claves están en formato long y se suelen representar en Hexadecimal. Si usáis ipcs para ver lo que habéis creado conviene que uséis ese formato para generar las claves. Una idea es hacer un #define MI_CLAVE 0x1234AFL. La L del final es importante para que el compilador sepa que es un long. En UNIX hay un procedimiento pseudo-estándar de generación de claves supuestamente únicas a través de ftok() y usando como identificador un fichero de nuestra aplicación. Su uso no es obligatorio pero si interesante saber en qué consiste.
  8. Otro problema a solventar con las colas de mensajes es entender como estructura los mensajes el sistema. Si creamos una cola de mensajes para nuestra aplicación, a través de esa cola podemos dejar mensajes de diferente tipo y los procesos que quieren leer mensajes pueden “sintonizarse” (es decir leer) mensajes de un tipo determinado. De esta forma podemos mantener varias comunicaciones simultáneas a través de la misma cola de mensajes.
  9. Habrá que decidir qué tipo de mensajes usar para cada comunicación y quienes intervienen en ello. Los tipos de mensaje es algo que forma parte del propio mensaje y que hay que saber utilizar adecuadamente. Un proceso receptor de mensajes puede “sintonizarse” en un tipo determinado vía msgrcv().
  10. Se aconseja usar etiquetas (flags) de compilación para decidir sobre el código de cada programa que versión compilar; si named-pipes o mensajes. De esta forma cualquier modificación en la lógica general se mantendrá actualizada para ambos casos y nos podemos centrar en cada caso en la forma de generalizar el uso de cada recurso. Se pueden activar estos flags de compilación desde el make.
  11. El diseño de la aplicación final que se propone de traducción de mensajes exige una reflexión previa de cómo utilizar la cola de mensajes. Un problema importante a resolver es cómo puede saber el servidor por dónde dar la respuesta al cliente. Aquí el alumno debe plantear alguna solución que seguramente le hará reflexionar sobre el concepto de “protocolo”.