Cteni z FIFO & vice procesu & fce select()

Martin Mačok martin.macok na underground.cz
Středa Leden 3 21:18:18 CET 2001


On Wed, Jan 03, 2001 at 08:23:12PM +0100, Tomas Rollbach wrote:
> uz delsi dobu se trapim s programem, ktery ma bezet ve vice instancich,
> pricemz kazda bude mit otevrenu rouru, do ktere jiny proces bude neco
> zapisovat. Chtel bych, aby kazdy proces pokazde precetl 1 znak, nejak ho
> zpracoval a cekal az se v roure objevi dalsi.
> 
> int main()
> {
>    int      fd, pid, cnt, retval, i;
>    fd_set   rfds;
>    char     c;
> 
>    fd=open("tst.fifo", O_NONBLOCK|O_RDONLY);
>    if(fd<0) { printf("%s\n", strerror(errno)); return -1; }
> 
>    pid=getpid();
>    printf("PID: %d\n", pid);
> 
>    for(i=0; i<10; i++)
>    {
>       FD_ZERO(&rfds);
>       FD_SET(fd, &rfds);
>       retval = select(fd+1, &rfds, NULL, NULL, NULL);
>       if(retval)
>       {
>          cnt=read(fd, &c, 1);
>          if(cnt==0) printf("%d: no char\n", pid);
>          if(cnt<0) printf("%d: %s\n", pid, strerror(errno));
>          if(cnt>0) printf("%d: %c\n", pid, c);
>       }
>    }
>    return 0;
> }
> 
> ktery zkompiluju a spustim ve trech kopiich, cimz dostanu vystup, napr:
> PID: 1549
> PID: 1553
> PID: 1551
> 
> Ted do roury neco zapisu:
> 
> $ echo "Baf babo" > tst.fifo
> 
> Coz provede nasledujici:
> 
> 1549: B
> 1553: a
> 1551: f
> 1551:
> 1553: b
> 1549: a
> 1549: b
> 1553: o
> 1551:
> 
> 1551: no char
> 1553: no char
> 1549: no char
> 1553: no char
> [...]
> 1551: no char
> 1553: no char
> 1549: no char
> 
> nacez vsechny procesy jaksepatri skonci.
> 
> Nechapu proc select pusti vykonavani programu, kdyz uz neni co cist! :-(((

Protoze se to od nej ocekava a je to tak navrzeno/zdokumentovano:

man select:

       Three independent sets of descriptors are watched.   Those
       listed  in  readfds  will  be watched to see if characters
       become available for reading (more precisely, to see if  a
       read  will not block - in particular, a file descriptor is
       also ready on end-of-file) ...

> Vim, ze by to slo udelat blokujicim read(), jenze ja v tom selectu() [az
> mi to bude chodit :-/ ] budu cekat jeste na dalsi descriptory, takze tohle
> pouzit nemuzu.
> 
> Muzete mi nekdo poradit, co tam je blbe a jak to ma byt spravne?

To zalezi, jak to presne chcete pouzit. Nejjednodussi je zaridit, aby
tam nikdo neposlal EOF. Anebo po zjisteni EOF rouru zavrit a znovu
otevrit vsemi ctecimi procesy ...

Anebo muzete zcela predelat design aplikace. Pokud trvate na FIFO, tak
nechte jeden hlavni proces cist znaky z FIFO a predavat je do do
fronty zprav (IPC messages) a nechte ty procesy, co ty znaky
zpracovavaji, cist z te fronty zprav.

Preji hezky den

P.S. Nevim, zda to vadi, ale pozor na "race conditions". Muze se stat,
ze dva procesy po sobe zavolaji select(), oboum to vrati priznak
pripravenosti cteciho deskriptoru, prvnimu se read podari a druhemu ne
.. jinymi slovy, pokud vam toto chovani vadi, je potreba uzavrit
operace select() a read() do kriticke sekce (napr. pomoci IPC
semaforu).

P.S.2 Pisu to tak nejak z hlavy, #include<standard_disclaimer.h>

-- 
   Martin Mačok
  underground.cz
    openbsd.cz


Další informace o konferenci Linux