pist2.c
, cuya adecuada compilación producirá
el ejecutable pist2
. Respetad las
mayúsculas/minúsculas de los nombres.
libpist.a
)
que debéis enlazar con vuestro módulo objeto para generar el
ejecutable. Gracias a ella, algunas de las funciones necesarias
para realizar la práctica no las tendréis
que programar sino que bastará nada más con incluir
la biblioteca cuando compiléis el programa. La línea de
compilación del programa podría ser:
c89 pist2.c libpist.a -o pist2 -lmDisponéis, además, de un fichero de cabeceras,
pist2.h
, donde se encuentran definidas, entre
otras cosas, las macros que usa la biblioteca y las cabeceras
de las funciones que ofrece.
PIST_inicio
con los parámetros adecuados. El proceso
será responsable de crear los procesos pistoleros
(un proceso hijo por cada pistolero que participe en la ronda)
y de controlar que,
si se pulsa CTRL+C la práctica acaba, no dejando procesos en
ejecución ni recursos IPCs sin borrar.
La práctica devolverá el número del pistolero que ha
sobrevivido ó 0 si no quedó ninguno. En el caso de que
se produzca un error, el código que se devolverá será
100.
libpist.a
son las que a continuación aparecen.
De no indicarse nada, las funciones devuelven -1 en caso de
error:
int PIST_inicio(unsigned int nPistoleros,
int ret, int semAforos,
char *zona, int semilla)
nPistoleros
el número de pistoleros,
en ret
la velocidad de presentación
(parámetro de la línea de órdenes)
y pasando el identificador del conjunto de
semáforos que se usará y el puntero a la zona
de memoria compartida declarada
para que la biblioteca pueda usarlos. El último
parámetro es la semilla del generador de números
pseudoaleatorios. De no haber sido especificada en
la línea de órdenes, pasad un cero.
int PIST_nuevoPistolero(char pist)
char PIST_vIctima(void)
int PIST_disparar(char pist)
int PIST_morirme(void)
int PIST_fin(void)
void pon_error(char *mensaje)
PIST_inicio
.
PIST_fin
.
PIST_nuevoPistolero
.
PIST_morirme
).
PIST_disparar
,
usaréis un
buzón de paso de mensajes. Se enviará un
mensaje de "MUERTE" al pistolero elegido.
No se usarán señales para matar a los
procesos, sino que "se suicidarán" una vez hayan
recibido uno o más mensajes de tipo "MUERTE".
PIST_morirme
y
se suicidarán.
sleep()
, se refiere a la llamada al sistema,
no a la orden de la línea de órdenes.
libpist.a
libpist.a
y el fichero de cabecera pist2.h
. La biblioteca
funciona con los códigos de VT100/xterm, por lo que debéis
adecuar
vuestros simuladores a este terminal.
libpist.a
:
para Solaris (ver 1.0),
para el LINUX de
clase (ver 1.0),
pist2.h
:
Para todos (ver 1.0).
ipcs
.
Es preferible, para que no haya interferencias, que
los defináis privados.
PIST_inicio
en
main
. Debe aparecer la pantalla de bienvenida
y, pasados dos segundos, dibujarse la pantalla.
PIST_nuevoPistolero
y ved que los PIDs que
aparecen en la pantalla coinciden con los suyos.
PIST_disparar
SEMÁFOROS Y VALOR INICIAL: SC=1, SV=0. SEUDOCÓDIGO: C V === === Por_siempre_jamás Por _siempre_jamás { { W(SC) W(SV) escribir_consonante escribir_vocal S(SV) S(SC) } }Daos cuenta que lo que importa en el pseudocódigo es la sincronización. El resto puede ir muy esquemático. Un buen esquema os facilitará muchísimo la defensa.
gcc
que os genere código de 32 bits para que vaya bien
con la biblioteca. Añadid -m32
en la
línea de compilación para lograrlo. Si os da
problemas al ejecutar el código es que necesitáis
instalar las bibliotecas de compatibilidad de 32 bits.
Dependiendo de la distribución se tratará de
un paquete u otro. Por ejemplo, para la familia
de Debian, se trata de un paquete llamado
ia32-libs
.
SIGINT
a los procesos que estén
en primer plano. Para probarlo, mandad el proceso
a primer plano con fg %
y pulsad
entonces CTRL+C.
int semAforo=-1
. En la
manejadora de SIGINT
, sólo si
semAforo
vale distinto de -1,
elimináis el recurso con semctl
.
Esto es lógico: si vale -1 es porque no se ha
creado todavía o porque al intentar crearlo
la llamada al sistema devolvió error. En ambos casos,
no hay que eliminar el recurso.
SIGINT
, podéis declarar una
estructura que los contenga a todos y así
sólo gastáis un identificador del espacio
de nombres globales.
wait
.
A vosotros os pasa con semop
, pero es
lo mismo. De las dos soluciones que propone el
apartado, debéis usar la segunda.
semctl
de
Solaris (con union semun
), como
se explica en la sesión de semáforos y no la de
HPUX.
Invalid argument
", pero, sin embargo,
se borren bien. La razón de esto es que habéis
registrado la manejadora de SIGINT
para
todos los procesos. Al pulsar CTRL+C, la señal la
reciben todos, el padre y los otros procesos. El primero
que obtiene la CPU salta a su manejadora y borra los
recursos. Cuando saltan los demás, intentan borrarlos,
pero como ya están borrados, os da el error.
Bus Error. Core dumped
si no definís el
puntero a esa variable apuntando a una dirección que
sea múltiplo de cuatro. El puntero que os devuelve
shmat
, no obstante, siempre será una
dirección múltiplo de cuatro, por lo que solo os
tenéis que preocupar con que la dirección sea
múltiplo de
cuatro respecto al origen de la memoria compartida.
La razón se escapa un poco al nivel de este curso y
tiene que ver con el alineamiento de direcciones de
memoria en las instrucciones de acceso de palabras en
el procesador RISC de encina.
Segmentation fault. Core dumped
",
la línea os la dará si aplicáis
lo que aparece en la
sección Manejo del depurador.
En cualquier otro caso, no os quedará más remedio que
depurar mediante órdenes de impresión dentro del
código.
fprintf(stderr,"...",...);donde sospechéis que hay problemas. En esas líneas identificad siempre al proceso que imprime el mensaje. Comprobad todas las hipótesis, hasta las más evidentes. Cuando ejecutéis la práctica, redirigid el canal de errores a un fichero con
2>salida
.
grep "P1" salida > salida2