Newsgroup: it.comp.os.linux.development
Titolo: Select ? Read Bloccante ?

Ciao a tutto il NG,
mi trovo un problema molto banale che non riesco a risolvere, ho
postato qui qualche tempo fa poi per mancanza di tempo ho ripreso in
mano il problema solo ora, riassumo quello che devo fare per chiarezza.
Devo unicamente leggere da una pipe quello che arriva e stampare su
schermo, il programma che legge da pipe fa da servizio e viene lanciato
prima di qualsiasi write, quindi si incarica di aprire la pipe e
mettersi in lettura, vorrei che la lettura fosse bloccante (la race
cond me la creo) a differenza dei problemi soliti che ci sono in giro.
Ultima nota: devo usare le pipe.
posto qui un pezzo di codice, spero possa aiutare:
    int i, Pipe = 0;
    fd_set fds;
    char Buffer[PIPELEN+1];
    // Open Named Pipe FIFO
    remove(NPNAME);
    if (mkfifo(NPNAME, 0660)<0) {
        return;
    }
    // Start SELECT
    Pipe = open(NPNAME, O_RDONLY);
    do {
        FD_ZERO(&fds);
        FD_SET(Pipe, &fds);
        if (select(Pipe+1, &fds, NULL, NULL, NULL)>0) {
            i = read(Pipe, Buffer, PIPELEN);
            lseek(Pipe, SEEK_SET, 0L);
            if (i<0) i=0;
            Buffer[i] = '\0';
            printf("DEBUG- Read: #%s#", Buffer);
        }
        printf(".");
    } while (1);
    close(Pipe); // inutile...
    return 0;
Ho provato a farlo con la sola read ed anche con select, come si vede
dall'esempio sopra, fino a quando non mando i primi caratteri su pipe
funziona tutto e il programma rimane fermo ad aspettare qualche tipo di
input, dopo che il primo programma esterno scrive su pipe (es. echo -e
-n "Ciao" > /tmp/named.pipe) il FD "Pipe" va in EOF e la select torna
sempre; stesso risultato se lascio stare select ed uso solo la read. La
soluzione potrebbe essere quella di chiudere ed aprire la pipe dopo
ogni read ma mi sembra una vaccata.
C'è qualche altro sistema per farlo.
Il mio vincolo principale è che il programma non deve sprecare cicli
ne andare in giro, la select nel mio caso deve bloccare il programma e
rimanere li, considerate che sto scrivendo il codice per un hw linux
embedded e le risorse non sono ovviamente quelle di un pc
Consigli ?
Grazie in anticipo per le risposte
Ben

 sempre;
Correttamente. echo apre la FIFO, scrive e chiude, quindi dall'altra
parte vedi l'EOF. Se dall'altra parte c'è un programma che apre, scrive
tutto l'output non ci sono problemi. Se invece hai (ad esempio) uno
script che esegue echo multipli puoi redirigere tutto lo stdout della
shell sulla FIFO usando exec:
exec > /tmp/named.pipe
echo Hello
echo World
echo !
In alternativa puoi ri-aprire solo quando read() restituisce 0.
Luca
-- 
Home: 
http://kronoz.cjb.net
"Sei l'unica donna della mia vita".
(Adamo)

 sempre;
Apri la pipe in read/write (O_RDWR). In questo modo, essendoci sempre un
processo con la pipe aperta in scrittura, non raggiungi mai l'EOF. 
Max

Ho fatto alcuni test, togliendo SELECT che in questo caso è
praticamente inutile sono arrivato a:
    Pipe = open(NPNAME, O_RDWR);
    do {
            i = read(Pipe, Buffer, PIPELEN);
            if (i<0) i=0;
            Buffer[i] = '\0';
            printf("DEBUG- Read: #%s#", Buffer);
        printf(".");
    } while (1);
    close(Pipe);
In questo modo c'è sicuramente in programma che tiene aperta la pipe
in scrittura, quello del demone stesso appunto.
Quello che non capisco è che a questo punto se mando
echo "Ciao" > /tmp/named.pipe
funziona, come dovrebbe... invece
echo -n "Ciao" > /tmp/named.pipe
non va, o meglio, i dati vengono mandati alla pipe, però la read non
ritorna fino a quando non chiudo tutto con un CR, quindi dalla prossima
echo "Ciao" > /tmp/named.pipe mi trovo (ovviamente) due "Ciao".
Perchè ? se il processo è finito non dovrebbe fare un flush
automatico ? L'unico modo di forzarlo è quello di seguire un CR finale
?
Grazie
Ben

 ritorna ...
Come fai a sapere che la 'read' non ritorna? Stai eseguendo il processo
sotto 'strace' o sotto gdb?
La successiva printf non ha un LF alla fine. Perciò, se nemmeno Buffer
contiene un LF,... (concludi tu).
Max