Perplessità processi (c,java,python, generico)

« Older   Newer »
  Share  
view post Posted on 12/1/2020, 13:10
Avatar

Immane Rompiball

Group:
Administrator
Posts:
18,287
Location:
Orlo esterno della cintura di Orione stella 1957

Status:


:lol:
 
Web  Top
view post Posted on 16/1/2020, 20:21
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Sempre restando in tema di processi, provo a chiedere, è più cosa da computer che da mirco...va bhè.
In C qualcuno di voi sa la teoria delle pipes ? comunicazione tra processi in pratica.
Ho delle perplessità...
 
Top
view post Posted on 16/1/2020, 22:46
Avatar

Noioso

Group:
Professionisti
Posts:
403

Status:


Le ho usate una sola volta, o meglio un paio ma la prima volta non si chiamavano tecnicamente "pipes"...
Poi ho trovato più pratico fare tutto con i socket TCP/IP, che valgono sia in locale che in rete.

Cosa vuoi sapere? :)
 
Top
view post Posted on 17/1/2020, 18:04
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Ciao Dario...bhè, diciamo che a tempo perso cerco di rispolverare argomenti un po' ostici del C:
processi, segnali, socket ecc...tutta roba che se fatta bene, ti porta via molto tempo e studio.
Le pipes come saprai, fanno comunicare 2 processi, con la clausola che devono avere un avo in comune.
Sono half-duplex, cioè mono direzionali...e qui viene la mia perplessità.
Supponiamo l'esempio (tralascia l'inutilità pratica).
Ho un padre e un figlio (con realtiva fork() in ambiente unix), il padre manda con una pipe al figlio un array di
int supponiamo, quindi uso una pipe che scrive al figlio.
Quindi nel padre chiudo il canale lettura, abilito quello di scrittura, inversa cosa nel figlio.
Ok, il figlio legge, elabora l'array e lo rispedisce al padre che lo stampa.
In un primo momento credevo che potessi usare una sola pipe, invece me ne servono 2.
La prima scrive al figlio e nel figlio legge, la seconda scrive al padre e il padre legge.
Non capisco se è giusto. Io intendevo (al 99% in modo errato) che fossero unidirezionali nel senso che mente scrivi
il canale di lettura è bloccato e viceversa, non che non le puoi riutilizzare.
Usando 2 pipes tutto funziona, una no.
Posso postare l'esempio nel caso, è per ambiente unix, ma credo che il concetto a parte la fork, la creazione della pipe
e il wait nel padre, tutto sia lo stesso anche in windows.
Sto facendo prove perchè mi piacerebbe abbinare i processi alla libreria ncurses, per rudimentali giochi tipo il bruco
tetrix ecc.
 
Top
view post Posted on 17/1/2020, 18:32
Avatar

Noioso

Group:
Professionisti
Posts:
403

Status:


Dunque, sì: immagino che in Linux/Unix la cosa sia leggermente diversa da come l'ho vista in Windows.
https://docs.microsoft.com/en-us/windows/w...-overlapped-i-o
Essendo assimilate a dei file (come peraltro anche le porte seriali o USB), Read e Write si possono fare *sempre*...

Ora dovrei andarmi a vedere com'è la cosa su Unix: se posti un pizzico di codice mi aiuti a cercare le info relative
 
Top
view post Posted on 17/1/2020, 19:36
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


ti posto il codice, è una cosa semplice.Appena riesco cerco di vedere il link che mi hai mandato.
Spero mantenga la formattazione, ma ne dubito :(

CODICE
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include  <string.h>
#define READ 0
#define WRITE 1

// WAITPID: ASPETTA CHE UN PROCESSO SPECIFICO FINISCA
// POI GLI ALTRI SONO RACCOLTI WAIT
//*************************************************
// esempio di comunicazione padre figlio:
// il padre manda un array con pipe0
// il figlio la legge con pipe 0, la elabora
// e la manda al padre con pipe1
// genn 2020


int main(int argc, char *argv[])
{
       int pid,x,i;
       int my_pipe_0[2];
       int my_pipe_1[2];
       int prova[4]={100,2,3,4};
       int buff[4];
       int status;
// creo le pipes
       if (pipe(my_pipe_0)==-1)
       {
               puts("errore");
               return -1;
       }

       if (pipe(my_pipe_1)==-1)
       {
               puts("errore");
               return -1;
       }
       
//********************************************
//                        figlio
//********************************************
       
       pid = fork();
       if ( pid == -1 )
       {
               printf ("Impossibile creare un nuovo processo\n");
               exit(1);
       }

       if ( pid == 0 )
       {
               int i;
               printf ("Sono il processo 0 figlio di %d, il mio PID è %d\n",getppid(), getpid());
               puts("leggo quello che mi manda il padre");
               close (my_pipe_0[WRITE]);// chiudo canale scrittura pipe0
               read(my_pipe_0[READ], buff, 4*sizeof(int)); //leggo quello che il padre manda
               close (my_pipe_0[READ]); // chiudo lettura pipe0
               for (i=0; i<4; i++)
               {
                       printf("child %d\n",buff[i]);
                       prova[i]=prova[i]*100;
               }

               close (my_pipe_1[READ]);// chiudo canale lettura pipe1
               write(my_pipe_1[WRITE], prova, 4*sizeof(int)); // scrivo con pipe1 al padre
               close (my_pipe_1[WRITE]); // chiudo canale scrittura pipe1
               puts("fine figlio");
               exit(0);
       }    

       
//************************************************************
//                        MAIN
//************************************************************
       if ( pid> 0 )
       {
               puts("sono nel main");
               close (my_pipe_0[READ]); //chiudo canale lettura pipe0
               write(my_pipe_0[WRITE], prova, 4*sizeof(int));//scrivo al figlio con pipe0
               close (my_pipe_0[WRITE]);// chiudo canale scrittura pipe0
               
//-------------------------------------------------------
               close (my_pipe_1[WRITE]); //chiudo canale scrittura pipe1
               read(my_pipe_1[READ], buff, 4*sizeof(int));//leggo cio che manda il figlio
               close (my_pipe_1[READ]);// chiudo canale lettura pipe1
               x=wait(&status);
               for (i=0 ;i<4 ;i++)
                       printf("BUFF %d\n",buff[i]);
               printf (" Il processo  %d è terminato con status %d\n", x,status);
       
       }
       return 0;

}
 
Top
view post Posted on 17/1/2020, 20:17
Avatar

Noioso

Group:
Professionisti
Posts:
403

Status:


Ok,
sto imparando cose nuove ora :) ma secondo un breve giro di documentazione,
https://it.wikipedia.org/wiki/Pipe_(informatica)
http://web.cse.ohio-state.edu/~mamrak.1/CI..._lab_notes.html

dice che vengono restituiti "descrittori entrambi usabili in lettura E scrittura" ...

Tu hai provato?
 
Top
view post Posted on 17/1/2020, 20:26
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


CITAZIONE
dice che vengono restituiti "descrittori entrambi usabili in lettura E scrittura" ...

Tu hai provato?

al momento non riesco a capire cosa intendi.
tu dici qui ?
CITAZIONE
A pipe can be explicitly created in Unix using the pipe system call. Two file descriptors are returned--fildes[0] and fildes[1], and they are both open for reading and writing. A read from fildes[0] accesses the data written to fildes[1] on a first-in-first-out (FIFO) basis and a read from fildes[1] accesses the data written to fildes[0] also on a FIFO basis.

nel momento della creazione, si hanno 2 descrittori : 0 per default lettura e 1 scrittura.
Se intendi questo, si, faccio in questo modo, ma il mio cruccio riguarda altro.
A dire il vero, sono molte cose che ancora non so.
Pipe, socket, segnali, è un argomento vastissimo
 
Top
view post Posted on 17/1/2020, 20:28
Avatar

Noioso

Group:
Professionisti
Posts:
403

Status:


Sì, intendevo quello:
a me sembra che tu abbia trovato necessario fare le "close" ogni volta, per cambiare il "comportamento" della Pipe, e invece da quello che leggo mi parrebbe che non serva.

O ti riferisci al fatto che se non fai close "i dati non appaiono" ossia la pipe in qualche modo non viene flush-ata?
 
Top
view post Posted on 17/1/2020, 20:36
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Domani ti posto la versione che a me sembra non funzionare. Usando cioè un pipe sola.
La chiusura dei canali non richiesti dovrebbe essere se mi sono documentato bene obbligatoria.
Se il figlio deve leggere, è raccomandato, se non tassativo (ripeto, se non erro) chiudere il canale di scrittura.
Domani, modifico il codice, e posto la versione che non mi funziona.
Intanto mi documento.
La mia idea, sarebbe quella di accoppiare processi con terminale "semigrafico" (ncurses).
Per esempio, il gioco del bruco: un processo, mi potrebbe leggere i tasti direzionali, un'altro la gestione
del bruco e via dicendo...sembra semplice, ma mica tanto.
Vedremo se mi riesce qualcosa di carino
 
Top
view post Posted on 17/1/2020, 20:40
Avatar

Noioso

Group:
Professionisti
Posts:
403

Status:


Sì ho capito più o meno cosa vuoi fare :) e direi che è ok.

Beh diciamo che questi sono "dettagli di implementazione", perché è ovvio che quello che stai cercando di fare è il motivo per cui esistono le Pipes.

Vediamo. Peccato non poter provare il tuo codice perché ho solo Windows...
 
Top
view post Posted on 17/1/2020, 20:52
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


CITAZIONE
Vediamo. Peccato non poter provare il tuo codice perché ho solo Windows...

e, si, mi sono avvicinato così per caso al mondo Unix, Ubuntu ecc, e a livello di sistema operativo mi trovo
un po' meglio, quindi mi sono fermato li.
Al massimo posto gli output che ottengo.
Come ultima cosa, poi domani posto il codice.
La mia impressione e che una pipe oltre essere mono direzionale, sia anche monouso. O almeno è questa la mia
perplessita'
pensavo che facendo:
padre( apro write e chiudo read)----->scrivo a figlio (chiudo write e apro read) (qui tutto ok)

quello che non funziona è questo (stessa pipe):
figlio (chiudo read, apro write)-----> scrivo a padre (chiudo write, apro read)
non va, se uso una seconda pipe si.
Allora la domanda è: una volta usata la pipe si "distrugge" ?
Qui è proprio questione di spulciare per bene la documentazione...
Intanto grazie Dario
 
Top
view post Posted on 17/1/2020, 21:01
Avatar

Noioso

Group:
Professionisti
Posts:
403

Status:


Sì, io personalmente trovo molto strano che tu la debba chiudere, per cui forse hai interpretato male la documentazione in tal senso: L'idea è che siano come dei "file", virtuali, che è come Windows le implementa, e quindi una volta aperti e in base alle loro possibilità di lettura/scrittura (poi per dire Windows ha il meccanismo dell'"attendi" oppure "segnala la fine lettura/scrittura" ma questo al momento non ci interessa, in nessun OS)

di nulla :) ciao!
 
Top
view post Posted on 18/1/2020, 11:54
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Riporto la versione che non mi funziona, che usa una pipe sola:
CODICE
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include  <string.h>
#define READ 0
#define WRITE 1

// WAITPID: ASPETTA CHE UN PROCESSO SPECIFICO FINISCA
// POI GLI ALTRI SONO RACCOLTI WAIT
//*************************************************
// esempio di comunicazione padre figlio:
// il padre manda un array con pipe0
// il figlio la legge con pipe 0, lo elabora
// e la manda al padre con pipe1
// genn 2020


int main(int argc, char *argv[])
{
       int pid,x,i;
       int my_pipe_0[2];
       int prova[4]={100,2,3,4};
       int buff[4];
       int status;
// creo le pipes
       if (pipe(my_pipe_0)==-1)
       {
               puts("erroer");
               return -1;
       }

       
       
//********************************************
//                        filglio
//********************************************
       
       pid = fork();
       if ( pid == -1 )
       {
               printf ("Impossibile creare un nuovo processo\n");
               exit(1);
       }

       if ( pid == 0 )
       {
               int i;
               printf ("Sono il processo 0 figlio di %d, il mio PID è %d\n",getppid(), getpid());
               puts("leggo quello che mi manda il padre");
               close (my_pipe_0[WRITE]);// chiudo canale scrittura pipe0
               read(my_pipe_0[READ], buff, 4*sizeof(int)); //leggo quello che il padre manda
               close (my_pipe_0[READ]); // chiudo lettura pipe0
               for (i=0; i<4; i++)
               {
                       printf("child %d\n",buff[i]);
                       prova[i]=prova[i]*100;
               }
               
               close (my_pipe_0[READ]);// chiudo canale lettura pipe0
               write(my_pipe_0[WRITE], prova, 4*sizeof(int)); // scrivo con pipe0 al padre
               close (my_pipe_0[WRITE]); // chiudo canale scrittura pipe0
               puts("fine figlio");
               exit(0);
       }    

       
//************************************************************
//                        MAIN
//************************************************************
       if ( pid> 0 )
       {
               puts("sono nel main");
               close (my_pipe_0[READ]); //chiudo canale lettura pipe0
               write(my_pipe_0[WRITE], prova, 4*sizeof(int));//scrivo al figlio con pipe0
               close (my_pipe_0[WRITE]);// chiudo canale scrittura pipe0
               
//-------------------------------------------------------
               close (my_pipe_0[WRITE]); //chiudo canale scrittura pipe0
               read(my_pipe_0[READ], buff, 4*sizeof(int));//leggo cio che manda il figlio
               close (my_pipe_0[READ]);// chiudo canale lettura pipe0
               x=wait(&status);
               for (i=0 ;i<4 ;i++)
                       printf("dati elaborati mandati dal figlio: %d\n",buff[i]);
               printf ("Il processo  %d è terminato con status %d\n", x,status);
       
       }
       return 0;

}


e i 2 output:
CODICE
gila@gila-pc:~/Scrivania$ ./xx
sono nel main
Sono il processo 0 figlio di 3197, il mio PID è 3198
leggo quello che mi manda il padre
child 100
child 2
child 3
child 4
fine figlio
dati elaborati mandati dal figlio: 10000
dati elaborati mandati dal figlio: 200
dati elaborati mandati dal figlio: 300
dati elaborati mandati dal figlio: 400
Il processo  3198 è terminato con status 0
/**********************************************************************

sono nel main
Sono il processo 0 figlio di 3280, il mio PID è 3281
leggo quello che mi manda il padre
child 100
child 2
child 3
child 4
fine figlio
dati elaborati mandati dal figlio: 0
dati elaborati mandati dal figlio: 0
dati elaborati mandati dal figlio: 0
dati elaborati mandati dal figlio: 0
Il processo  3281 è terminato con status 0
gila@gila-pc:~/Scrivania$


il secondo output come si nota, perde i valori.
Comunque leggendo qui:
CITAZIONE
Nei sistemi operativi una pipe è uno degli strumenti disponibili per far comunicare tra loro dei processi. Le pipe, diversamente dai socket, offrono un canale di comunicazione monodirezionale, e quindi occorre impiegarne due per ottenere una comunicazione bidirezionale.

tratto da wikipedia, sembrerebbe proprio che ce ne vogliano 2.
Riguardo al discorso di aprire e chiudere i canali, anche li dovrebbe essere come dico...però...
Sto cercando di simulare una broken pipe, cioè un errore che dovrebbero dare canali aperti simultaneamente, ma non
mi riesce. Non so, forse bisogna tirare in ballo pure i segnali.
Insomma, è un argomento molto vasto.
A dire il vero (eterna domanda), mi domando se tutto ciò ha senso per un livello hobbistico...bho!!!
 
Top
view post Posted on 18/1/2020, 12:14
Avatar

Noioso

Group:
Professionisti
Posts:
403

Status:


Dunque, ok per il monodirezionale ma continuo a pensare che quelle close() siano errate... magari prova!

Vedo che sono citati i socket anche qua, e quindi torno a pensare che decisamente siano una soluzione migliore! Tra l'altro l'indirizzo 127.0.0.1 dovrebbe essere disponibile sempre anche se non c'è la scheda di rete, per quanto poi oggigiorno tutti hanno una scheda di rete.

Stavo però pensando anche... non dovresti "aspettare", specie in lettura, che i dati siano presenti? Il tuo codice "passa" attraverso le write (diciamo che questo è ok) e le read (e qua non so...) senza aspettare che i dati siano passati... qualcosa tipo un "check data ready"?


Be' il senso ce l'ha sempre :) per imparare!
 
Top
159 replies since 6/1/2020, 21:09   1137 views
  Share