Discussione:
Matrice di pipes - System calls linux
(troppo vecchio per rispondere)
Max
2014-07-14 09:38:51 UTC
Permalink
Ho provando a fare questo esercizio:

Si progetti in ambiente Unix/C la seguente interazione di processi:
- il sistema consiste di N+1 processi che interagiscono a due a due
tramite una delle N pipe disponibili: la pipe p_i è utilizzata in lettura
dal processo P_i e in scrittura dal processo P_i-1 ;
- il processo P_0 inoltra il proprio pid nella pipe e attende l'arrivo di un
segnale;
- ogni processo P_i (con i<N) preleva il messaggio dalla pipe p_i e lo
scrive nella pipe p_i+1 ;
- il processo P_N, ricevuto il pid di P_0, provvede ad inviargli un
segnale SIGUSR1.



Consigli del docente del corso:
1)Abbiamo un processo padre e N suoi processi figli
2)La struttura dati che deve contenere le pipe deve essere una matrice
di N righe e due colonne.



Questo il mio tentativo:




#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#define N 10


void Gestione(int s){
printf("Segnale ricevuto\n");
}


int main()
{
int i,pid,ptoken;
int matfd[N][2];
for(i=0;i<N;i++)
pipe(matfd[i]); //creo le N pipe su cui far passare il pid del padre

for(i=0;i<N;i++){
pid=fork();
if(pid==-1) {perror("Errore fork\n"); _exit(1);}
if (pid==0) {
printf("Processo P%d\t",i+1); close(matfd[i][1]); close(matfd[i+1][0]);
//chiudo i "lati" delle pipe su cui non devo leggere/scrivere
read(matfd[i][0],&ptoken,sizeof(int)); printf("Ptoken: %d\n",ptoken);
if (i==(N-1)) {kill(ptoken,SIGUSR1); _exit(0);} //ossia sono l'ultimo
processo figlio e mando il segnale al padre
else {write(matfd[i+1][1],&ptoken,sizeof(int)); _exit (0);}
}
}

ptoken=getpid();
printf("Pid padre(P0): %d",ptoken);
signal(SIGUSR1,Gestione);
close (matfd[0][0]); write(matfd[0][1],&ptoken,sizeof(int));

pause();
return 0;


}


Pare funzioni, ma siccome ho l'esame tra breve, vorrei un vostro parere
e qualche consiglio.

Forse come codice è un pochino troppo "sporco" credo...

Ci sarebbe un' alternativa usando exec: separando il codice del padre da
quello del generico figlio, e passando la "i" del for come stringa alla
exec, per poi riconvertirla in numero nel figlio usando una cosa come:
int i; sscanf(argv[1],"%d",&i), cosi' potrei gestire le pipe "i" e
"i+1" del generico figlio, ma non ci ho neanche provato, temo
impazzirei!!! :-)
m***@gmail.com
2014-07-14 17:29:11 UTC
Permalink
Post by Max
[...]
[...]
int main()
{
int i,pid,ptoken;
int matfd[N][2];
for(i=0;i<N;i++)
pipe(matfd[i]); //creo le N pipe su cui far passare il pid del padre
Quando chiami una syscall dovresti *sempre* controllare eventuali errori.
Post by Max
[...]
if (pid==0) {
printf("Processo P%d\t",i+1); close(matfd[i][1]); close(matfd[i+1][0]);
//chiudo i "lati" delle pipe su cui non devo leggere/scrivere
Non mi sembra necessario chiudere le pipe; è una cosa che si fa solo in un programma che deve gestire molti files.
Post by Max
read(matfd[i][0],&ptoken,sizeof(int)); printf("Ptoken: %d\n",ptoken);
Controlla eventuali errori di read
Post by Max
if (i==(N-1)) {kill(ptoken,SIGUSR1); _exit(0);} //ossia sono l'ultimo
processo figlio e mando il segnale al padre
else {write(matfd[i+1][1],&ptoken,sizeof(int)); _exit (0);}
Controlla eventuali errori di write.
Post by Max
[...]
signal(SIGUSR1,Gestione);
close (matfd[0][0]); write(matfd[0][1],&ptoken,sizeof(int));
pause();
Cosa fai nella funzione pause?
Post by Max
return 0;
Pare funzioni, ma siccome ho l'esame tra breve, vorrei un vostro parere
e qualche consiglio.
Forse come codice � un pochino troppo "sporco" credo...
Sicuramente.
Vedi se riusci a spostare qualcosa in funzioni separate.
Inoltre la formattazione del codice era pessima, spero sia colpa del client NNTP.
Post by Max
Ci sarebbe un' alternativa usando exec: separando il codice del padre da
quello del generico figlio, e passando la "i" del for come stringa alla
Perchè mai dovresti fare una cosa del genere?
Inoltre se chiami exec, processo padre e figlio non condividono più la memoria, e non puoi usare le pipe anonime.
Post by Max
[...]
Ciao Manlio
Jack
2014-07-14 17:42:44 UTC
Permalink
Post by m***@gmail.com
Post by Max
printf("Processo P%d\t",i+1); close(matfd[i][1]); close(matfd[i+1][0]);
//chiudo i "lati" delle pipe su cui non devo leggere/scrivere
Non mi sembra necessario chiudere le pipe; è una cosa che si fa solo in un
programma che deve gestire molti files.
e' cosa buona e giusta liberare le risorse non piu' utilizate.

Ciao Jack
--
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?
m***@gmail.com
2014-07-15 11:09:57 UTC
Permalink
Post by Jack
Post by Max
printf("Processo P%d\t",i+1); close(matfd[i][1]); close(matfd[i+1][0]);
//chiudo i "lati" delle pipe su cui non devo leggere/scrivere
Non mi sembra necessario chiudere le pipe; � una cosa che si fa solo in un
programma che deve gestire molti files.
e' cosa buona e giusta liberare le risorse non piu' utilizate.
Si, ma sono risorse che libera automaticamente il kernel non appena il processo termina (ossia, in questo caso, quasi subito).

Inoltre se proprio vuoi liberare risorse non più utilizzate, allora le devi liberare *tutte* (ossia, in questo caso, tutte i file descriptors ereditate dal processo padre, esclusi i due che vengono usati).
Post by Jack
[...]
Ciao Manlio

Max
2014-07-15 08:24:07 UTC
Permalink
Post by m***@gmail.com
Post by Max
[...]
[...]
int main()
{
int i,pid,ptoken;
int matfd[N][2];
for(i=0;i<N;i++)
pipe(matfd[i]); //creo le N pipe su cui far passare il pid del padre
Quando chiami una syscall dovresti *sempre* controllare eventuali errori.
vero, questa però è stata solo pigrizia...
Post by m***@gmail.com
Post by Max
pause();
Cosa fai nella funzione pause?
Aspetto che uno dei miei figli mi mandi un segnale con kill.
Post by m***@gmail.com
Sicuramente.
Vedi se riusci a spostare qualcosa in funzioni separate.
Inoltre la formattazione del codice era pessima, spero sia colpa del client NNTP.
No, sono io che quando vado di fretta metto le parentesi un pò a
casaccio :-P
Post by m***@gmail.com
Post by Max
Ci sarebbe un' alternativa usando exec: separando il codice del padre da
quello del generico figlio, e passando la "i" del for come stringa alla
Perchè mai dovresti fare una cosa del genere?
Come diceva il prof al corso: per mantenere "maggior pulizia"

Grazie per i commenti.
Loading...