sábado, 3 de abril de 2010
Encrucijada (III: Mejor subida)
Encrucijada (y II: Solución)
Padre
Leer_línea_comandos();
Crea_IPCS();
Prepara_IPCS();
CRUCE_inicio();
W(procesos);
Nace_ciclo_semafórico();
Por siempre jamás{
W(procesos);
Nace_coche_o_peatón();
}
Acabar
Si padre{
CRUCE_fin();
W(max_proc-1)(procesos);
Destruye_IPCS();
Muere();
} Si no{
Muerte_hijo();
}
Muerte_hijo
S(procesos);
Muere();
Ciclo_semafórico
SemC2 = Rojo;
Por siempre jamás{
W(P1);
SemP1 = Rojo;
SemC1 = Verde;
SemP2 = Verde;
S(C1) S(P2);
Pausa⁶();
W(C1) W(P2);
SemC1 = Amarillo;
SemP2 = Rojo;
Pausa²();
W(Cruce);
SemC1 = Rojo;
S(Cruce);
SemC2 = Verde;
S(C2);
Pausa⁸();
W(C2);
SemC2 = Amarillo;
Pausa²();
W(Cruce);
SemC2 = Rojo;
S(Cruce);
SemP1 = Verde;
S(P1);
Pausa⁶();
Coche
CRUCE_inicio_coche();
Mientras(posicion_válida){
Mueve_coche();
Pausa();
}
Fin_coche();
Envia_mensajes_última_posición();
Muerte_hijo();
Mueve_coche
Si (pos = posC1){
W(C1) W(Cruce);
Recibe_mensajes_pos_sig();
avanza();
S(C1);
} Si No si (pos == posC2){
W(C2);
Recibe_mensajes_pos_sig();
avanza();
S(C2);
}Si no{
Si (pos == pos_cruce){
W(Cruce);
}
Recibe_mensajes_posicion_sig();
avanza();
}
Si (sales_del_cruce){
S(Cruce);
}
Si (pos_anterior_válida){
Envia_mensajes_pos_anterior();
}
actualiza_pos_anterior();
}
Peatón
W(Nacer);
Nace();
Recibe_mensaje_pos_nac();
Mientras(posición_válida){
Mueve_peatón();
Mueve_peatón();
Pausa();
}
Fin_peatón();
Envía_mensaje_última_pos();
Muerte_hijo();
Mueve_peatón
Si (sale_zona_nacimiento){
S(Nacer);
}
Recibe_mensaje_pos_sig();
Si (pos == posP1){
W(P1);
Muevete();
S(P1);
} Si no Si(pos == posP2){
W(P2);
Muevete();
S(P2);
} Si no{
Muevete();
}
Si (anterior_válido){
Envía_mensaje_pos_anterior();
}
Actualiza_anterior();
Código
#include "cruce.h"
#include
#include
#include
#include
#include
#include
#include
#include
#define EXERR 1
//#define _HPUX
#define _PEAT
#define _SEMA
#define _COCH
#define _MSGS
void morir(int sennal);
void terminar(int sennal);
void exhortizar(int sennal);
int nace_hijo();
void muerte_peat();
void muerte_coch();
void muerte_hijo();
void ciclo_semaforico();
void coche();
int pos_valida(struct posiciOn);
void peaton();
void error();
int semaforo = -1, mcomp = -1, buzon = -1;
int ppid;
char * pmem = NULL;
int max_proc;
#ifndef _HPUX
union semun{
int val;
struct semid_ds *buf;
ushort_t *array;
};
#endif
typedef struct mensaje{
long tipo;
char info;
} mensaje;
int main(int argc, char * argv[]){
struct sigaction manejadora;
struct sembuf procesos[1];
#ifndef _HPUX
union semun sem;
#endif
int vel, tipo;
int i, j;
long tipomen;
mensaje msg;
if(argc != 3){
printf("Error en el paso de argumentos.\n");
return 1;
}
max_proc = atoi(argv[1]);
vel = atoi(argv[2]);
ppid = getpid();
manejadora.sa_handler = morir;
if(sigfillset(&manejadora.sa_mask) == -1) return EXERR;
manejadora.sa_flags = 0;
if(sigaction(SIGINT, &manejadora, NULL) == -1)return EXERR;
manejadora.sa_handler = terminar;
if(sigemptyset(&manejadora.sa_mask) == -1)return EXERR;
manejadora.sa_flags = 0;
if(sigaction(SIGTERM, &manejadora, NULL) == -1)return EXERR;
if(signal(SIGCHLD, SIG_IGN) == SIG_ERR)return EXERR;
semaforo = semget(IPC_PRIVATE, 9, IPC_CREAT|0600);
if(semaforo == -1) error();
mcomp = shmget(IPC_PRIVATE, 256, IPC_CREAT|0600);
if(mcomp == -1)error();
pmem = (char *)shmat(mcomp, NULL, 0);
if(pmem == NULL) error();
buzon = msgget(IPC_PRIVATE, IPC_CREAT|0600);
if(buzon == -1) error();
#ifndef _HPUX
sem.val = max_proc-1;
if(semctl(semaforo, 1, SETVAL, sem) == -1)error();
sem.val = 0;
if(semctl(semaforo, 2, SETVAL, sem) == -1)error();
sem.val = 0;
if(semctl(semaforo, 3, SETVAL, sem) == -1)error();
sem.val = 1;
if(semctl(semaforo, 4, SETVAL, sem) == -1)error();
sem.val = 0;
if(semctl(semaforo, 5, SETVAL, sem) == -1)error();
sem.val = 1;
if(semctl(semaforo, 6, SETVAL, sem) == -1)error();
sem.val = 1;
if(semctl(semaforo, 7, SETVAL, sem) == -1)error();
#else
if(semctl(semaforo, 1, SETVAL, max_proc-1) == -1)error();
if(semctl(semaforo, 2, SETVAL, 0) == -1)error();//Semáforos C1
if(semctl(semaforo, 3, SETVAL, 0) == -1)error(); //C2
if(semctl(semaforo, 4, SETVAL, 1) == -1)error(); //P1
if(semctl(semaforo, 5, SETVAL, 0) == -1)error(); //P2 según como estarían al acabar la ultima fase
if(semctl(semaforo, 6, SETVAL, 1) == -1)error(); //CRUCE
if(semctl(semaforo, 7, SETVAL, 1) == -1)error(); //NACE
#endif
for(i = 0; i <= 16; i++){
for(j = 0; j <= 50; j++){
msg.tipo = 1 + i*100 + j;
msg.info = 'v';
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1)error();
}
}
procesos[0].sem_num = 1;
procesos[0].sem_op = -1;
procesos[0].sem_flg = 0;
CRUCE_inicio(vel, max_proc, semaforo, pmem);
#ifdef _SEMA
if(semop(semaforo, procesos, 1) == -1)error();
switch(nace_hijo()){
case 0:
ciclo_semaforico();
return 1;
}
#endif
while(1){
if(semop(semaforo, procesos, 1) == -1)kill(0, SIGTERM);
tipo = CRUCE_nuevo_proceso();
switch(nace_hijo()){
case 0:
switch (tipo){
#ifdef _COCH
case COCHE:
coche();
#endif
#ifdef _PEAT
case PEAToN:
peaton();
#endif
default:
muerte_hijo();
}
default:
break;
}
}
}
void error(){
struct shmid_ds buf;
if(semaforo != -1) semctl(semaforo, 0, IPC_RMID);
if(mcomp != -1){
shmdt(pmem);
shmctl(mcomp, IPC_RMID, &buf);
}
if(buzon != -1) msgctl(buzon, IPC_RMID, NULL);
_Exit(EXERR);
}
void morir(int sennal){
struct sembuf sem[1];
struct shmid_ds buf;
sem[0].sem_flg = 0;
if(getpid() == ppid){
CRUCE_fin();
sem[0].sem_num = 1;
sem[0].sem_op = -(max_proc - 2);
if(semop(semaforo, sem, 1) == -1) kill(0, SIGTERM);
if(semaforo != -1) if(semctl(semaforo, 0, IPC_RMID) == -1) kill(0, SIGTERM);
if(mcomp != -1){
if(shmdt(pmem) == -1) kill(0, SIGTERM);
if(shmctl(mcomp, IPC_RMID, &buf) == -1) kill(0, SIGTERM);
}
if(buzon != -1) if(msgctl(buzon, IPC_RMID, NULL) == -1) kill(0, SIGTERM);
}
else{
muerte_hijo();
}
_Exit(0);
}
void terminar(int sennal){
struct shmid_ds buf;
if(getpid() == ppid){
CRUCE_fin();
if(semaforo != -1) semctl(semaforo, 0, IPC_RMID);
if(mcomp != -1){
shmdt(pmem);
shmctl(mcomp, IPC_RMID, &buf);
}
if(buzon != -1) msgctl(buzon, IPC_RMID, NULL);
}
else{
muerte_hijo();
}
_Exit(EXERR);
}
void muerte_hijo(){
struct sembuf procesos[1];
procesos[0].sem_num = 1;
procesos[0].sem_op = 1;
procesos[0].sem_flg = 0;
if(semop(semaforo, procesos, 1))kill(0, SIGTERM);
_Exit(0);
}
int nace_hijo(){
int pid;
if(ppid == getpid()){
pid = fork();
switch(pid){
case -1:
kill(0, SIGTERM);
break;
case 0:
return 0;
default:
return pid;
}
}
}
void ciclo_semaforico(){
struct sembuf pon_sem[3];
pon_sem[0].sem_flg = 0;
pon_sem[1].sem_flg = 0;
pon_sem[2].sem_flg = 0;
CRUCE_pon_semAforo(SEM_C2, ROJO);
while(1){
pon_sem[0].sem_num = 4;
pon_sem[0].sem_op = -1; //P1
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
CRUCE_pon_semAforo(SEM_P1, ROJO);
pon_sem[0].sem_num = 2;
pon_sem[0].sem_op = 1;//C1
pon_sem[1].sem_num = 5;
pon_sem[1].sem_op = 1; //P2
CRUCE_pon_semAforo(SEM_C1, VERDE);
CRUCE_pon_semAforo(SEM_P2, VERDE);
if(semop(semaforo, pon_sem, 2))kill(0, SIGTERM);
pausa();
pausa();
pausa();
pausa();
pausa();
pausa();
pon_sem[0].sem_num = 2;
pon_sem[0].sem_op = -1;//C1
pon_sem[1].sem_num = 5;
pon_sem[1].sem_op = -1; //P2
if(semop(semaforo, pon_sem, 2))kill(0, SIGTERM);
CRUCE_pon_semAforo(SEM_C1, AMARILLO);
CRUCE_pon_semAforo(SEM_P2, ROJO);
pausa();
pausa();
pon_sem[0].sem_num = 6; //CRUCE
pon_sem[0].sem_op = -1;
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
CRUCE_pon_semAforo(SEM_C1, ROJO);
pon_sem[0].sem_op = 1;
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
CRUCE_pon_semAforo(SEM_C2, VERDE);
pon_sem[0].sem_num = 3; //C2
pon_sem[0].sem_op = 1;
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
pausa();
pausa();
pausa();
pausa();
pausa();
pausa();
pausa();
pausa();
pon_sem[0].sem_num = 3;
pon_sem[0].sem_op = -1;//C2
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
CRUCE_pon_semAforo(SEM_C2, AMARILLO);
pausa();
pausa();
pon_sem[0].sem_num = 6;
pon_sem[0].sem_op = -1;
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
CRUCE_pon_semAforo(SEM_C2, ROJO);
pon_sem[0].sem_op = 1; //amar
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
CRUCE_pon_semAforo(SEM_P1, VERDE);
pon_sem[0].sem_num = 4; //P1
pon_sem[0].sem_op = 1;
if(semop(semaforo, pon_sem, 1))kill(0, SIGTERM);
pausa();
pausa();
pausa();
pausa();
pausa();
pausa();
}
}
struct posiciOn mueve_coche(struct posiciOn pos, struct posiciOn * anterior){
struct sembuf procesos[1], semc1[2], semc2[2], amarillo[1];
struct mensaje msg, msg_ant;
long tipo;
struct posiciOn sig;
semc1[0].sem_num = 2;
semc1[0].sem_op = -1;
semc1[0].sem_flg = 0;
semc2[0].sem_num = 3;
semc2[0].sem_op = -1;
semc2[0].sem_flg = 0;
semc2[1].sem_num = 6; //CRUCE
semc2[1].sem_op = -1;
semc2[1].sem_flg = 0;
semc1[1].sem_num = 6; //CRUCE
semc1[1].sem_op = -1;
semc1[1].sem_flg = 0;
amarillo[0].sem_num = 6;
amarillo[0].sem_op = -1;
amarillo[0].sem_flg = 0;
#ifdef _SEMA
if((pos.y == 6) && (pos.x == 33)){
if(semop(semaforo, semc1, 2))kill(0, SIGTERM);
#ifdef _MSGS
tipo = 1 + pos.y*100 + (pos.x);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 1);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 2);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 3);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 4);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
#endif
sig = CRUCE_avanzar_coche(pos);
semc1[0].sem_op = 1;
if(semop(semaforo, semc1, 1))kill(0, SIGTERM);
}
else if((pos.y == 10) && (pos.x == 13)){
if(semop(semaforo, semc2, 1))kill(0, SIGTERM);
#ifdef _MSGS
tipo = 1 + (pos.y)*100 + (pos.x + 5);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-1)*100 + (pos.x + 5);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-2)*100 + (pos.x + 5);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y)*100 + (pos.x + 6);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-1)*100 + (pos.x + 6);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-2)*100 + (pos.x + 6);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
#endif
sig = CRUCE_avanzar_coche(pos);
semc2[0].sem_op = 1;
if(semop(semaforo, semc2, 1))kill(0, SIGTERM);
}else{
#ifdef _MSGS
if (pos.x == 33 && pos.y == 6){
amarillo[0].sem_num = 6;
amarillo[0].sem_op = -1;
if(semop(semaforo, amarillo, 1))kill(0, SIGTERM);
} else if(pos.x == 23 && pos.y == 10){
amarillo[0].sem_num = 6;
amarillo[0].sem_op = -1;
if(semop(semaforo, amarillo, 1))kill(0, SIGTERM);
}
if(pos.x == 33 && pos.y == 10 && anterior->y == 10 && anterior->x == 31){
tipo = 1 + (pos.y + 1)*100 + (pos.x);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y + 1)*100 + (pos.x + 1);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y + 1)*100 + (pos.x + 2);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y + 1)*100 + (pos.x + 3);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y + 1)*100 + (pos.x + 4);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
}
else if(pos.x < y ="="">
tipo = 1 + (pos.y)*100 + (pos.x + 5);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-1)*100 + (pos.x + 5);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-2)*100 + (pos.x + 5);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y)*100 + (pos.x + 6);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-1)*100 + (pos.x + 6);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + (pos.y-2)*100 + (pos.x + 6);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
}
else if(pos.y <= 16 ){
tipo = 1 + pos.y*100 + (pos.x);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 1);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 2);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 3);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
tipo = 1 + pos.y*100 + (pos.x + 4);
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
}
#endif
sig = CRUCE_avanzar_coche(pos);
}
#else
sig = CRUCE_avanzar_coche(pos);
#endif
if(pos.x == 33 && pos.y == 13){
amarillo[0].sem_op = 1;
if(semop(semaforo, amarillo, 1) == -1) kill(0, SIGTERM);
}
if((anterior->x != -1) && (anterior->y != -1)){
if(pos.x == 33 && pos.y == 10 && anterior->y == 10 && anterior->x == 31){
msg.tipo = 1 + (anterior->y - 2)*100 + (anterior->x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 1)*100 + (anterior->x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y)*100 + (anterior->x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 2)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 1)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
}
else if(anterior->x <= 31 && anterior->x == 1){
msg.tipo = 1 + (anterior->y - 2)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 1)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
}
else if(anterior->x <= 31 && anterior->x >= 3){
msg.tipo = 1 + (anterior->y - 2)*100 + (anterior->x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 1)*100 + (anterior->x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y)*100 + (anterior->x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 2)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 1)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
}
else if (pos.x == 33 && pos.y == 12 && anterior->y == 10 && anterior->x == 33);
else if (anterior->y > 4 && anterior->x >31 && pos.y <>
msg.tipo = 1 + (anterior->y - 4)*100 + (anterior->x + 4);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 4)*100 + (anterior->x + 3);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 4)*100 + (anterior->x + 2);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 4)*100 + (anterior->x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior->y - 4)*100 + (anterior->x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
}
}
if (pos.x == 33 && pos.y == 10 && anterior->y == 10 && anterior->x == 31){
anterior->x = 33;
anterior->y = 10;
}else{
anterior->x = pos.x;
anterior->y = pos.y;
}
return sig;
}
void coche(){
struct sembuf procesos[1];
struct posiciOn pos, anterior = {-1, -1};
struct mensaje msg;
procesos[0].sem_num = 1;
procesos[0].sem_op = 1;
procesos[0].sem_flg = 0;
pos = CRUCE_inicio_coche();
while(1){
pos = mueve_coche(pos, &anterior);
if(!pos_valida(pos)) break;
pausa();
}
CRUCE_fin_coche();
msg.tipo = 1 + (anterior.y - 4)*100 + (anterior.x + 4);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior.y - 4)*100 + (anterior.x + 3);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior.y - 4)*100 + (anterior.x + 2);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior.y - 4)*100 + (anterior.x + 1);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
msg.tipo = 1 + (anterior.y - 4)*100 + (anterior.x);
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
muerte_hijo();
}
int pos_valida(struct posiciOn pos){
if(pos.y <>
else return 1;
}
struct posiciOn mueve_peaton(struct posiciOn pos, struct posiciOn * anterior){
struct posiciOn sig;
struct sembuf semp2[1], semp1[1], semnac[1];
struct mensaje msg, msg_ant;
static int critica = 1;
long tipo;
semp2[0].sem_num = 5;
semp2[0].sem_flg = 0;
semp2[0].sem_op = -1;
semp1[0].sem_num = 4;
semp1[0].sem_flg = 0;
semp1[0].sem_op = -1;
semnac[0].sem_num = 7;
semnac[0].sem_flg = 0;
semnac[0].sem_op = -1;
tipo = 1 + pos.x + pos.y*100;
if(((anterior->y == 16 && anterior->x <>x == 0 && anterior->y <= 16 && anterior->y > 11)) && (critica == 0)){
semnac[0].sem_op = -1;
if(semop(semaforo, semnac, 1) == -1) kill(0, SIGTERM);
critica = 1;
} else if ((anterior->y <= 15 && (anterior->x > 0)) && (critica == 1)){
semnac[0].sem_op = 1;
if(semop(semaforo, semnac, 1) == -1) kill(0, SIGTERM);
critica = 0;
}
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
#ifdef _SEMA
if((pos.x <> 20) && (pos.y == 11)){
if(semop(semaforo, semp2, 1) == -1) kill(0, SIGTERM);
sig = CRUCE_avanzar_peatOn(pos);
semp2[0].sem_op = 1;
if(semop(semaforo, semp2, 1) == -1) kill(0, SIGTERM);
}
else if((pos.y <> 12) && (pos.x == 30)){
if(semop(semaforo, semp1, 1) == -1) kill(0, SIGTERM);
sig = CRUCE_avanzar_peatOn(pos);
semp1[0].sem_op = 1;
if(semop(semaforo, semp1, 1) == -1) kill(0, SIGTERM);
}
else sig = CRUCE_avanzar_peatOn(pos);
#else
sig = CRUCE_avanzar_peatOn(pos);
#endif
if((anterior->x != -1) && (anterior->y != -1)){
msg_ant.tipo = 1 + anterior->x + anterior->y*100;
if(msgsnd(buzon, &msg_ant, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
}
anterior->x = pos.x;
anterior->y = pos.y;
return sig;
}
void peaton(){
struct sembuf procesos[1], semnac[1];
struct posiciOn pos, anterior = {-1, -1};
struct mensaje msg;
long tipo;
procesos[0].sem_num = 1;
procesos[0].sem_op = 1;
procesos[0].sem_flg = 0;
semnac[0].sem_num = 7;
semnac[0].sem_op = -1;
semnac[0].sem_flg = 0;
if(semop(semaforo, semnac, 1) == -1) kill(0, SIGTERM);
pos = CRUCE_inicio_peatOn_ext(&anterior);
tipo = 1 + anterior.y*100 + anterior.x;
if(msgrcv(buzon, &msg, sizeof(mensaje), tipo, MSG_NOERROR) == -1) kill(0, SIGTERM);
while(1){
pos = mueve_peaton(pos, &anterior);
if(!pos_valida(pos)) break;
pos = mueve_peaton(pos, &anterior);
if(!pos_valida(pos)) break;
pausa();
}
msg.tipo = 1 + anterior.x + anterior.y*100;
msg.info = 'v';
CRUCE_fin_peatOn();
if(msgsnd(buzon, &msg, sizeof(mensaje) - sizeof(long), 0) == -1) kill(0, SIGTERM);
muerte_hijo();
}
Encrucijada (I: Enunciado)

cruce.c, cuya adecuada compilación producirá el ejecutable cruce. Respetad las mayúsculas/minúsculas de los nombres. libcruce.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:gcc cruce.c libcruce.a -o crucecruce.h, donde se encuentran definidas, entre otras cosas, las macros que usa la biblioteca y las cabeceras de las funciones que ofrece. CRUCE_inicio con los parámetros adecuados. El proceso será responsable de crear los procesos adicionales necesarios. Cada peatón o cada coche simulado será representado mediante un proceso, hijo del proceso principal. También es responsabilidad del primer proceso el 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á 0 en caso de ejecución satisfactoria o un número mayor que cero, en caso de detectarse un error. libcruce.a son las que a continuación aparecen. De no indicarse nada, las funciones devuelven -1 en caso de error:- int CRUCE_inicio(int ret, int maxProcs, int semAforos, char *zona)El primer proceso, después de haber creado los mecanismos IPC que se necesiten y antes de haber tenido ningún hijo, debe llamar a esta función, indicando en
retla velocidad de presentación y enmaxProcsel número máximo de procesos permitidos en esta ejecución (parámetros ambos de la línea de órdenes) y pasando además 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. - int CRUCE_pon_semAforo(int sem, int color)Pone el semáforo
semal colorcolor. El primer parámetro puede ser:SEM_P1,SEM_P2,SEM_C1,SEM_C2, para los semáforos de peatones y coches, respectivamente. El segundo parámetro puede valer:ROJO,AMARILLO(solamente para los semáforos de coches) oVERDE. Estas son todas macros definidas encruce.h. - int CRUCE_nuevo_proceso(void)El padre, después de haber creado todo lo necesario, se encuentra en un bucle infinito en el que va generando los nuevos procesos, coches o peatones. Esta función le devuelve
COCHEoPEAToNpara que sepa de qué tipo es el proceso que tiene que crear a continuación. struct posiciOn CRUCE_inicio_coche(void)ystruct posiciOn CRUCE_inicio_peatOn(void)El nuevo proceso hijo, dependiendo de si es coche o peatón, llamará a una de estas dos funciones. La función correspondiente devolverá las coordenadas de la posición siguiente del objeto recién creado. La funciónCRUCE_inicio_peatOnes desaconsejada. Úsese mejor la siguiente función.- struct posiciOn CRUCE_inicio_peatOn_ext(struct posiciOn *posNacimiento)El nuevo proceso hijo, si es un peatón, llamará a esta función. La función devolverá las coordenadas de la posición siguiente del peatón recién creado y la posición de nacimiento en el parámetro pasado por referencia. Esta función sustituye a la correspondiente del apartado anterior.
struct posiciOn CRUCE_avanzar_coche(struct posiciOn sgte)ystruct posiciOn CRUCE_avanzar_peatOn(struct posiciOn sgte)El proceso, después de haber llamado a la función anterior, se mete en un bucle de avance. A esta función se le pasa la posición a la que se quiere ir y devuelve la nueva posición siguiente. Del bucle se saldrá cuando en la coordenada y de la posición devuelta haya un valor menor que cero.int pausa_coche(void)eint pausa(void)Entre dos avances consecutivos, los coches llaman a la primera función y los peatones a la segunda. La segunda función también sirve para medir las pausas del ciclo semafóricoint CRUCE_fin_coche(void)eint CRUCE_fin_peatOn(void)El proceso hijo que haya salido del bucle de avance, invoca esta función.- int CRUCE_fin(void)El padre, una vez sabe que ha acabado la práctica y antes de realizar limpieza de procesos y mecanismos IPC debe llamar a esta función.
- void pon_error(char *mensaje)Pone un mensaje de error en el recuadro azul de la parte inferior de la pantalla y espera a que el usuario pulse "Intro". La podéis usar para depurar.
- Tomará los datos de la línea de órdenes y los verificará.
- Iniciará las variables, mecanismos IPC, manejadoras de señales y demás.
- Llamará a la función
CRUCE_inicio. - Creará el proceso gestor semafórico.
- Entrará en un bucle infinito del que solamente saldrá si se pulsa CTRL+C. Dentro del bucle:
- Si hay tantos procesos como el máximo declarado, se queda esperando, sin consumo de CPU, hasta que muera alguno.
- Llamará a la función
CRUCE_nuevo_proceso, que responderá indicando de qué tipo será: coche o peatón. - Creará un proceso hijo, que ejecutará las funciones correspondientes a su tipo.
- Cuando se pulse CTRL+C, se engargará de finalizar todo ordenadamente.
- Establecerá el estado de los semáforos de tráfico según en la fase en que nos encontremos.
- Dormirá, sin consumo de CPU, el tiempo correspondiente a esa fase.
sleep(), se refiere a la llamada al sistema, no a la orden de la línea de órdenes. Ciclo semafórico

- Primera fase: C1 y P2 en verde. El resto, en rojo. Duración: 6 pausas(*).
- Segunda fase: C2 en verde. El resto, en rojo. Duración: 8 pausas.
- Tercera fase: P1 en verde. El resto, en rojo. Duración: 12 pausas.
pausa(). Biblioteca de funciones libcruce.a
libcruce.a y el fichero de cabeceras cruce.h. La biblioteca funciona con los códigos de VT100/xterm, por lo que debéis adecuar vuestros simuladores a este terminal. También se usa la codificación UTF-8, por lo que necesitáis un programa de terminal que sepa interpretarlos. Los terminales de Linux lo hacen por defecto, pero si usáis Windows, debéis aseguraros de que el programa tiene capacidad para interpretarlos y que esta capacidad está activada. Si no es así notaréis caracteres basura en la salida de modo que no se verá nada.Ficheros necesarios:
libcruce.a: para Solaris (ver 2.0), para el LINUX de clase (ver 2.0),cruce.h: Para todos (ver 2.0).
Registro de versiones:
- 1.0: primera versión
- 1.1: un error hace que no se reconozca bien al padre en
CRUCE_nuevo_proceso - 1.2: la biblioteca tenía preferencia por sacar coches en la dirección horizontal
- 2.0: para controlar el nacimiento de los peatones es necesario conocer no solamente su posición siguiente, sino también, su posición de nacimiento. Para ello, se crea una nueva función:
CRUCE_nuevo_peatOn_ext