El programa constará de un solo fichero fuente,
ascensor.c
. Sin embargo, este único programa
fuente, al ejecutarse, generará cinco procesos en total:
uno para el funcionamiento del ascensor y cuatro más para
las personas que lo usan: Alberto, Benito, Carmen y Daniela.
El edificio donde se encuentra el ascensor tiene cuatro plantas, del bajo hasta el tercero. En el ascensor caben como máximo dos personas.
Los personajes se encuentran al principio sentados en el piso tercero y el ascensor está situado en la planta baja. Cada uno de los personajes realiza la misma ruta sin descanso:
El ascensor tarda un segundo en pasar de una planta a la
siguiente. Está conectado con los procesos mediante dos
tuberías sin nombre, referidas mediante las variables
tubo1
y tubo2
. Por tubo1
recibe el ascensor las llamadas que realizan los procesos desde
el exterior del ascensor para que este vaya a un piso. Por
tubo2
recibe las correspondientes llamadas desde
el interior del ascensor. El ascensor permanecerá parado
sin consumir CPU y con la puerta cerrada
hasta que reciba una petición
proveniente de cualquiera de las tuberías. Dará prioridad a
las peticiones realizadas desde el exterior. Cuando recibe una
petición, se moverá hasta el piso solicitado, esperará un
segundo, abrirá la puerta y esperará tres segundos más.
Cerrará después la puerta y volverá a esperar más peticiones.
Cada uno de los personajes, por su parte, se pondrá de pie,
solicitará por tubo1
que el ascensor vaya al piso
en el que esté
y esperará a que el ascensor llegue. Si el ascensor llega lleno,
descansará cuatro segundos y esperará a que, por fortuna, vuelva
a parar en ese piso. Si en el ascensor hay sitio, entrará en él
(tarda 1 segundo en hacerlo), realizará por tubo2
la petición del piso al que desea ir y esperará a que el
ascensor llegue. Cuando se abra la puerta, saldrá del ascensor
(tarda un segundo en salir), esperará un segundo antes de
sentarse, esperará 15 segundos más si es hombre y 10 segundos
más si es mujer y continuará su ruta.
Para realizar la práctica se usará un conjunto de cuatro semáforos, uno para cada piso. El ascensor liberará el semáforo de cada planta cuando pare en ella y haya abierto la puerta. El ascensor tomará (decrementará) el semáforo de una planta antes de cerrar la puerta. Debéis diseñar cuándo toman y liberan los semáforos los procesos de los personajes.
Para realizar la representación gráfica de lo que ocurre en
cada momento, se usará una biblioteca de funciones que tenéis
a vuestra disposición en el fichero
libascensor.a
.
Para usarla, debéis incluir en vuestro código fuente el fichero
de cabecera
libascensor.h
.
Las funciones de las que disponéis en esa biblioteca
son las siguientes:
int inicio_ascensor(int sem,
struct datos_ascensor* sdap)
:sem
es una variable entera que contendrá
el identificador de un conjunto con un único semáforo
que sea accesible por el proceso. sdap
debe
contener un puntero a una zona de memoria compartida con
capacidad suficiente para alojar una estructura del tipo
struct datos_ascensor
, definida en
libascensor.h
.
int refrescar(void)
:int abrir_puerta(void)
int cerrar_puerta(void)
:int ir_piso(int piso)
:int persona_de_pie(int persona)
int persona_sentada(int persona)
:int persona_dentro(int persona)
int persona_fuera(int persona)
:int personas_dentro(void)
:
En las funciones que admiten como parámetro una persona se
usará el siguiente convenio: Alberto (0), Benito (1),
Carmen (2) y Daniela (3). Todas las funciones de la biblioteca
devuelven -1 si la operación que se pretende realizar es
incorrecta. Además, indicarán en la pantalla la operación y
el error que se ha producido. Para comprobar el funcionamiento
de la biblioteca se puede ver el ejemplo proporcionado en los
ficheros Makefile
y
prueba.c
.
En este ejemplo, se muestra cómo funciona la biblioteca y
cómo se pueden enlazar las funciones con vuestro código.
Tened en cuenta que en el ejemplo se usa memoria
dinámica porque sólo hay un proceso, pero vosotros tendréis
que usar memoria compartida para que funcione con
varios procesos.
Para que un proceso si lo necesita conozca,
en general, la situación del problema en cada
momento, puede consultar la zona de memoria compartida cuyo
puntero se pasó a la función inicio_ascensor
.
En esta zona se alojará una estructura
de tipo struct datos_ascensor
definida en
libascensor.h
que será actualizada solamente
por las funciones de la biblioteca. Los campos más interesantes
de esta estructura son los siguientes:
int pos[4]; /* 0-> bajo, 1->1º, ..., 3->3º, -1-> ascensor */ int puerta[4]; /* 0-> cerrada, 1-> abierta */ int sentada[4]; /* 1-> sentada, 0-> de pie */ int piso_ascensor; /* 0..3 */
pos
es un array de cuatro elementos que
nos da la posición de cada personaje.
puerta
es un array de cuatro elementos
que nos indica si una puerta está cerrada o abierta.
sentada
es un array de cuatro elementos
donde se especifica si un personaje está sentado o no.
piso_ascensor
es una variable entera que
contiene el piso donde se encuentra el ascensor en estos
momentos.
Se considerará falta grave que cualquier proceso realice un consumo innecesario de CPU.
Para todas las pausas, se puede usar la función de biblioteca
sleep()
.
Al pulsar CTRL+C
acabará el programa, habiendo
limpiado previamente los objetos IPC usados (semáforos y
memoria compartida). Ningún proceso debe sobrevivir a la
pulsación de CTRL+C
.
libascensor.a
son ficheros que contienen
el código máquina de algunas funciones listo para ser
enlazado con un programa del usuario. Al tratarse de
código máquina, no es transportable entre diferentes
arquitecturas y, posiblemente, sistemas operativos.
Quiere esto decir que libascensor.a
no
va a funcionar en Linux. Podéis probar con una versión
generada con un Red Hat 5.2:
libascensor.a
. O con otra para una
Red Hat 7.0:
libascensor.a
.
Si fuera necesario,
ya os pondría la biblioteca compilada para otras
versiones de Linux.