Corvo80
24-09-2005, 15:30
Salve a tutti, ho un problemino... Il seguente programma dovrebbe generare N processi figlio (nell'esempio N e'uguale a 2) e ciascuno di essi deve inviare separatamente al padre (che si occupa di gestire il servizio di stampa a video) due linee di testo del tipo "#x: linea 1" e "#x: linea 2", dove x e'l'identificativo del processo (da 1 a N). Tramite l'utilizzo dei semafori, si assicura che linee di diversi processi non possano essere stampati in maniera accavallata.
#include "pv.h" /* Struttura che definisce i semafori */
#include <stdlib.h>
#include <time.h>
#define N 2 /* Numero di processi, definire a piacere */
#define R 1 /* Numero di iterazioni per processo, definire a piacere */
int p(int semid); /* Funzione di accesso alla sezione critica */
int v(int semid); /* Funzione di uscita dalla sezione critica */
int initsem(key_t skey); /* Funzione di inizializzazione del semaforo */
void handlesem(key_t skey, int i, int outp); /* Funzione di gestione del semaforo */
struct msgst {
int proc; /* numero del processo */
int line; /* numero della riga da stampare */
};
main() {
key_t semkey = 0x200;
int i;
pid_t pid;
int p[2];
if(pipe(p)==-1) {
perror("pipe call");
exit(1);
}
for (i=1; i<=N; i++) { /* Crea N processi... */
pid=fork();
if (pid == 0) {
close(p[0]);
struct msgst dati_msg;
dati_msg.proc=i;
dati_msg.line=1;
handlesem(semkey, i, p[1]);
}
else if (pid > 0) {
/* Processo padre */
close(p[1]);
struct msgst valore_letto;
int j;
for (j=1; j<=N*R*2; j++) {
read(p[0],&valore_letto,sizeof(valore_letto));
printf("# %i: linea %i\n", valore_letto.proc, valore_letto.line);
}
}
else {
printf("Si e' verificato un errore nella chiamata a fork.\n"); /* ... ERRORE */
exit(2);
}
}
}
int initsem(key_t semkey) {
int status = 0, semid;
if((semid = semget(semkey, 1, SEMPERM | IPC_CREAT | IPC_EXCL)) == -1) { /* Crea un array di un semaforo e controlla che non si verifichino errori */
if(errno == EEXIST)
semid = semget(semkey, 1, 0);
}
else { /* Se tutto e'andato bene... */
semun arg;
arg.val = 1;
status = semctl(semid, 0, SETVAL, arg); /* Inizializza il semaforo a valore 1 */
}
if(semid == -1 || status == -1) { /* Gestisci eventuali errori */
perror("initsem fallita");
return (-1);
}
return semid;
}
void handlesem(key_t skey, int proc, int outp) {
int semid;
pid_t pid = getpid();
if((semid = initsem(skey)) < 0) /* Esci in caso di errore */
exit(1);
struct msgst dati_msg1;
dati_msg1.proc=proc;
dati_msg1.line=1;
struct msgst dati_msg2;
dati_msg2.proc=proc;
dati_msg2.line=2;
int j;
for (j = 1; j<=R; j++) { /* Ciascun processo ripete R volte... */
/* prima della sezione critica */
p(semid);
/* all interno della sezione critica */
write(outp,&dati_msg1,sizeof(dati_msg1)); /* Invia prima riga */
write(outp,&dati_msg2,sizeof(dati_msg2)); /* Invia seconda riga */
/* in procinto di abbandonare la sezione critica */
v(semid);
/* in procinto di terminare */
srandom(time(0)+proc);
sleep((int)random()%3+1); /* Dormi un tempo pseudocasuale */
}
exit(0); /* Fine */
}
int p(int semid) {
struct sembuf p_buf;
p_buf.sem_num = 0; /* Semaforo su cui effettuare l'operazione */
p_buf.sem_op = -1; /* valore negativo: forma generalizzata della funzione p() */
p_buf.sem_flg = SEM_UNDO; /* Valore predefinito */
if(semop(semid, &p_buf, 1) == -1) { /* Gestisci eventuali errori */
perror("p(semid) fallita");
exit(1);
}
return(0);
}
int v(int semid) {
struct sembuf v_buf;
v_buf.sem_num = 0; /* Semaforo su cui effettuare l'operazione */
v_buf.sem_op = 1; /* valore positivo: forma generalizzata della funzione v() */
v_buf.sem_flg = SEM_UNDO; /* Valore predefinito */
if(semop(semid, &v_buf, 1) == -1) { /* Gestisci eventuali errori */
perror("v(semid) fallita");
exit(1);
}
return(0);
}
Ecco il problema: dovrebbe risultare un output del tipo:
# 1: linea 1
# 1: linea 2
# 2: linea 1
# 2: linea 2
E invece risulta...
# 1: linea 1
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
Dove sbaglio? Grazie della disponibilita'...
#include "pv.h" /* Struttura che definisce i semafori */
#include <stdlib.h>
#include <time.h>
#define N 2 /* Numero di processi, definire a piacere */
#define R 1 /* Numero di iterazioni per processo, definire a piacere */
int p(int semid); /* Funzione di accesso alla sezione critica */
int v(int semid); /* Funzione di uscita dalla sezione critica */
int initsem(key_t skey); /* Funzione di inizializzazione del semaforo */
void handlesem(key_t skey, int i, int outp); /* Funzione di gestione del semaforo */
struct msgst {
int proc; /* numero del processo */
int line; /* numero della riga da stampare */
};
main() {
key_t semkey = 0x200;
int i;
pid_t pid;
int p[2];
if(pipe(p)==-1) {
perror("pipe call");
exit(1);
}
for (i=1; i<=N; i++) { /* Crea N processi... */
pid=fork();
if (pid == 0) {
close(p[0]);
struct msgst dati_msg;
dati_msg.proc=i;
dati_msg.line=1;
handlesem(semkey, i, p[1]);
}
else if (pid > 0) {
/* Processo padre */
close(p[1]);
struct msgst valore_letto;
int j;
for (j=1; j<=N*R*2; j++) {
read(p[0],&valore_letto,sizeof(valore_letto));
printf("# %i: linea %i\n", valore_letto.proc, valore_letto.line);
}
}
else {
printf("Si e' verificato un errore nella chiamata a fork.\n"); /* ... ERRORE */
exit(2);
}
}
}
int initsem(key_t semkey) {
int status = 0, semid;
if((semid = semget(semkey, 1, SEMPERM | IPC_CREAT | IPC_EXCL)) == -1) { /* Crea un array di un semaforo e controlla che non si verifichino errori */
if(errno == EEXIST)
semid = semget(semkey, 1, 0);
}
else { /* Se tutto e'andato bene... */
semun arg;
arg.val = 1;
status = semctl(semid, 0, SETVAL, arg); /* Inizializza il semaforo a valore 1 */
}
if(semid == -1 || status == -1) { /* Gestisci eventuali errori */
perror("initsem fallita");
return (-1);
}
return semid;
}
void handlesem(key_t skey, int proc, int outp) {
int semid;
pid_t pid = getpid();
if((semid = initsem(skey)) < 0) /* Esci in caso di errore */
exit(1);
struct msgst dati_msg1;
dati_msg1.proc=proc;
dati_msg1.line=1;
struct msgst dati_msg2;
dati_msg2.proc=proc;
dati_msg2.line=2;
int j;
for (j = 1; j<=R; j++) { /* Ciascun processo ripete R volte... */
/* prima della sezione critica */
p(semid);
/* all interno della sezione critica */
write(outp,&dati_msg1,sizeof(dati_msg1)); /* Invia prima riga */
write(outp,&dati_msg2,sizeof(dati_msg2)); /* Invia seconda riga */
/* in procinto di abbandonare la sezione critica */
v(semid);
/* in procinto di terminare */
srandom(time(0)+proc);
sleep((int)random()%3+1); /* Dormi un tempo pseudocasuale */
}
exit(0); /* Fine */
}
int p(int semid) {
struct sembuf p_buf;
p_buf.sem_num = 0; /* Semaforo su cui effettuare l'operazione */
p_buf.sem_op = -1; /* valore negativo: forma generalizzata della funzione p() */
p_buf.sem_flg = SEM_UNDO; /* Valore predefinito */
if(semop(semid, &p_buf, 1) == -1) { /* Gestisci eventuali errori */
perror("p(semid) fallita");
exit(1);
}
return(0);
}
int v(int semid) {
struct sembuf v_buf;
v_buf.sem_num = 0; /* Semaforo su cui effettuare l'operazione */
v_buf.sem_op = 1; /* valore positivo: forma generalizzata della funzione v() */
v_buf.sem_flg = SEM_UNDO; /* Valore predefinito */
if(semop(semid, &v_buf, 1) == -1) { /* Gestisci eventuali errori */
perror("v(semid) fallita");
exit(1);
}
return(0);
}
Ecco il problema: dovrebbe risultare un output del tipo:
# 1: linea 1
# 1: linea 2
# 2: linea 1
# 2: linea 2
E invece risulta...
# 1: linea 1
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
# 1: linea 2
Dove sbaglio? Grazie della disponibilita'...