Newsgroup: it.comp.os.linux.development
Titolo: Dubbi sulla comunicazione interprocesso

Salve a tutti,
sto sperimentando un po' con le pipe sotto linux (in C) ma ci sono un po' di 
cose che non mi sono chiare:
- supponiamo di avere una pipe bloccante: e' vero che una scrittura/lettura 
completa sempre, anche per dimensioni maggiori del buffer? (es.: se da un 
lato della pipe scrivo 10 MB di dati e dall'altro faccio una read di 
dimensione 10 MB, sia la write che la read termineranno avendo scritto e 
letto tutti i 10 MB? Saro' sicuro di aver trasferito tutti i dati?)
- se invece la pipe e' non bloccante cosa succede? Diciamo che scrivo sempre 
10 MB: la write scrive PIPE_BUF byte e poi termina? La read legge PIPE_BUF 
byte e poi termina?
- se si', come faccio a risolvere questo problema: il mio processo comunica 
tramite due pipe con un altro processo, e contemporaneamente comunica 
bidirezionalmente con un dispositivo seriale; quello che faccio ora e' un 
polling continuo sui vari canali (vedo se c'e' qualcosa in pipe, se si' 
leggo e scrivo sulla seriale; vedo se c'e' qualcosa sulla seriale, se si' 
leggo e scrivo sulla pipe), quindi devono essere tutte letture non bloccanti 
(se non ci sono dati), ma bloccanti quando ci sono dati (per rimanere li' 
fino a che non ho letto tutto il pacchetto dati). La seriale l'ho impostata 
come bloccante e faccio una "ioctl(fd, FIONREAD, &nbytes);" per vedere 
quando c'e' roba da leggere, posso fare lo stesso con la pipe?
Grazie,
Pleg

 Pleg
Ciao
Roberto.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 che sono appunto dei multiplex.
Si avevo pensato anche alla select ma se si puo' usare la ioctl sono piu' 
contento (la lettura da pipe e la lettura da seriale possono avere 
impostazioni diverse, tipo una con timeout e l'altra no, quindi non posso 
usare una unica select per tenere sotto controllo tutti i file descriptor, 
dovrei cmq usarne una per la pipe e una per la seriale).
Pleg

 dovrei cmq usarne una per la pipe e una per la seriale).
Non l' ho capita.
Perche non si puo' gestire l' ascissa temporale con i timeouts ordinati
e ognuno associato al proprio handler? Comunque select avra' come
timeout "il prossimo".


 timeout "il prossimo".
Si' hai ragione, mi sembrava overkill "scomodare" una select per una cosa 
del genere ma in effetti va benissimo lo stesso.
Grazie di tutto l'aiuto,
Pleg 

Ho sperimentato un po' sia con la ioctl che con la select... ma non sono 
risucito a ottenere molto piu' di risultati per me incomprensibili :-)
Allora: stesso programma gia' postato, con queste modifiche:
- nel processo figlio inserisco un ritardo (tramite sleep() ) prima di 
spedire i dati con la write
- nel processo genitore inserisco un ciclo che continua a testare lo stato 
della pipe finche' la pipe non risulta piena: a quel punto fa partire la 
read
Per il processo genitore ho provato queste due alternative:
IOCTL:
do {
 ioctl(fd[0], FIONREAD, &nbytes);
 printf("nbytes = %d\n", nbytes);
 usleep(200000);
} while(nbytes <= 0);
SELECT:
do {
 sel = select(max_fd, &input_fd, NULL, NULL, &select_timeout);
 printf("sel = %d\n", sel);
} while(sel <= 0);
Risultati per me incomprensibili:
- sotto linux (debian lenny) la select va o non va a seconda di quando la 
effettuo rispetto alla write:
    - se la select avviene DOPO che il processo figlio ha fatto (cominciato) 
la write, la prima volta che la chiamo esce subito con risultato 1 (dati 
disponibili) e la read parte senza problemi
    - se la select avviene PRIMA che il processo figlio ha fatto 
(cominciato) la write, restituisce SEMPRE 0 (cioe' timeout); la cosa ancor 
piu' strana e' che la prima volta che esegue aspetta effettivamente il tempo 
che ho impostato in "select_timeout", le volte successive no ma va a ritmo 
continuo (esempio di quello che vedo a schermo: se metto la select_timeout a 
1 secondo, la select aspetta un secondo, dopo un secondo mi ritrovo a video 
"sel = 0" e poi parte una sequenza infinita e continua, rapidissima di "sel 
= 0", come se il timeout fosse scomparso, annullato)
- sotto linux (debian lenny) la ioctl funziona sempre: per qualche volta 
restituisce 0, poi resituisce 65536 (che e' corretto, visto che leggo che 
dal kernel linux 2.6.11 il PIPE_BUF e' stato portato a 64 kiB), e a quel 
punto la read parte correttamente
- sotto cygwin su WinXP, ne' la select ne' la ioctl funzionano 
(restituiscono sempre e cmq 0) (cmq devo usare TIOCINQ al posto di FIONREAD, 
che non esiste).
Qualche suggerimento?
C'e' qualche libro "guru" che mi consigliate per risolvere questi enigmi 
(che pensavo fossero nozioni abbastanza elementari, in realta')? Lo Stevens 
vale davvero la pena? Magari lo prendo.
Thx,
Pleg

 rapidissima di "sel = 0", come se il timeout fosse scomparso, annullato)
E' giusto: come dice lo Stevens, quando la select va in timeout (nessun 
descrittore pronto) succedono due cose:
- tutti i descrittori vengono annullati (ecco perche' dopo la prima volta 
non leggo piu' una cippa! non sto controllando piu' nulla!)
- la struttura timeval viene settata al valore di tempo restante (0 nel mio 
caso), ma solo in linux 2.4.22+ (dice che in FReeBSD, Solaris e MacOS invece 
la timeval non viene toccata, come mi aspettavo io) (ecco perche' dopo la 
prima volta la select parte impazzita!)
Il problema e' che in rete si trova tutto e il contrario di tutto, ad 
esempio qui 
http://www.lilik.it/~mirko/gapil/gapilsu169.html
 (verso la 
meta') dice che "Se invece si ha un timeout viene restituito un valore nullo 
e gli insiemi non vengono modificati", cosa evidentemente non vera (me ne 
accorgo semplicemente facendomi stapare a video i valori dei descrittori 
prima e dopo la select, e si vede chiaramente che vengono azzerati).
Quindi: il ciclo SELECT postato in precedenza funziona tranquillamente come 
mi aspettavo se dopo ogni select() (quando il valore restituito e' pari a 0, 
cioe' e' andata in timeout) si ha l'accortezza di risettare sia la struct 
timeval che i descrittori.
Sorry per questo monologo, sono niubbio di C e UNIX e sto cercando di 
imparare :-)
Pleg