pipe olvasasa

 ( kaltsi | 2008. szeptember 24., szerda - 15:17 )

Lehet elég rossz megoldást választottam, de szeretnék neves pipe-ot olvasni.
Beállítottam rá egy select-et, ami szépen működik is. Bár kiolvasom a pipe-ot, és itt jön a gond, hogy én csak \n-ig akarom kiolvasni. de akár a fgets-et, akár fscanf-et használok, kiolvasás után a select visszadob, hogy van adat a pipe-ban, és annak olvasásakor Segmentation fault-ot kapok. Ha másképp nem megy ciklusba szervezem, de hátha van ötletetek, egy frappáns megoldásra.
köszi

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

talan ha a kodot is megosztanad nem csak a problemat...

(ne felejtsd a < code > taget hasznalni - persze a ket szokoz nelkul).

Hát nem egy nagy kódrész, az egész kicsit hosszú lenne. Akkor a lényeg:

             pipe=open(config.pipe_location,O_RDONLY | O_NONBLOCK)
.
.
.
.
                if(FD_ISSET(pipe,&setSocks))
                {
                    FILE *stream;
                    stream = fdopen (pipe, "r");
                    fgets(data_buffer,sizeof(data_buffer)-1,stream);
         # vagy ez:        fscanf(stream,"%s\n",data_buffer);
                    fclose(stream);
                }

De lehet hogy 0 hosszú, azaz üres pipe-ot nem tudok stream-re nyitni?

És valóban egy üres pipe megnyitása stream-re nil-t eredményez. Vagy az a baj, hogy bezárom, és nem csak a stream záródik be?

Ures pipe ebben az esetben azt jelenti hogy a masik alkalmazas nem nyitotta meg egyatalan a named fifo-t vagy azt, hogy megnyitotta, irkalt is bele valamit, de mar lezarta/kilepett? Mindesetre egy, a peer altal lezart fd-re ranyitni fdopen()-nel, az tenyleg nem lehet a legszebb (bar igazabol kerdes, hogy mit csinal az az fdopen()? elvileg buffer-elokeszitesen kivul mast nem nagyon kene; a `man fdopen` errol nem ir tul sokat).

en ebben egyetlen arva selectet sem latok akarhogyan is eroltetem a szemem...

ket megjegyzes:
- ne hasznalj NONBLOCK-ot. a nonblock rossz. foleg ha select()a'lsz is kozben.
- ne hasznalj bufferelt olvasast. bufferelt olvasas (fgets/fscanf/fread..., de ilyen az SSL_read(), ... stb is) rossz, ha select()a'lsz is kozben: i.e. lehet hogy mar 3 sor is benne van a bufferben, az fgets() ezt soronkent vissza is adja/adna', adat viszont nem jon a pipe-rol, tehat ket eset lehetseges: 1/ vagy nincs vege a file-nak, ekkor a select() blokkolni fog az idok vegezeteig 2/ vege van a file-nak, ekkor minden select() rogton visszater (eof is FD_ISSET-et valt ki, ha read allapotra pollozol) de ilyenkor a raolvasas, foleg ha bufferelt, csunya lehet, pl szegfault. Az fgets() fv-ek raadasul kicsit elbaltazva adjak vissza a file vege allapotot: egy while ( ! feof(fr) ) { fgets(...); } ciklussal duplan kapod pl vissza az utolso sort, ha az nem \n-re vegzodik (mindenfele select es egyeb bonya dolog nelkul is).

köszi, megoldom másképp

Igen, sajnos ebbe a problemaba en is tobbszor belefutottam (mondjuk inkabb socket-ekkel, de a lenyeg ugyanez). A megoldas mindig az volt, hogy tisztan read/write fv-k hasznalata + kezi buffereles, ugy semmi gond nem volt me'g. Ha kell egy kis egyszeru api erre, azt tudok kuldeni.

A.

Nekem mindig a sorokra tores a gondom. A fgets azert jo, mert csak egy sort ad vissza \n nelkul, pont ezert szeretem hasznalni. Meg lehet ilyesmit oldani read/write-tal, azaz hogy soronkent olvassam a fajlt? Mennyire bonyi ezt megcsinalni?
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Az fgets is szerintem benne hagyja a \n-t, de lehet hogy rosszul emlekszem (igazabol az a legkevesebb, ha mondjuk utana a sorokat szokozok alapjan bontod darabokra).

Valami ilyesmit csinaltam anno a problema'ra:

linebuffer_reset(&lb);
while ( main_loop )
 {  ...
    FD_SET(f1,...)
    FD_SET(f2,...)
    select(max+1,...,...,...,...);
    ...
    if ( FD_ISSET(fx,...) )
     {  n=read(fx,tempbuff,tempbuffsize);
        if ( n<0 )
         {   /* error */ ... }
        else if ( n==0 ) /* EOF */
         {   line=linebuffer_flush(&lb);
             if ( line != NULL )
              {     do_something_with_partial_line(line);
                    free(line);
              }
             linebuffer_free(&lb);
         }
        else /* normal data */
         {   linebuffer_concatenate(&lb,tempbuff,n);
             while ( (line=linebuffer_fetch(&lb)) != NULL )
              {     do_something_with_line(line);
                    free(line);
              }
         }
     } 
    ....  
 }

lenyeg, hogy a beolvasott adatot hozzacsapod egy bufferhez, majd egeszen addig, ameddig vannak benne "sorok", azaz \n-nel hatarolt reszek, azokat kiszeded, feldolgozod. A legvegen, EOF-kor pedig vagy tokures a buffer, vagy egy reszleges sor van benne (azaz nincs a vegen \n, kulonben az elozo ciklus kiszedte ma'r volna). Azzal kis kezdesz valamit, oszt annyi. A lenyeg, hogy senki sem garantalja, hogy 1/ a read()-dal beolvasol egy teljes sort 2/ a read()-dal pontosan 1 sort olvasol be, es nem mondjuk 137-et. szerk: 3/ azt sem hogy a file legvegen teljes sort talalsz. Ezeket mind kulon kell kezelni, sajnos.

Engem igazabol a linebuffer_* megvalositasok erdekeltek volna...
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Pl. ennek a forrasaban benne van, ./src/linebuffer.[ch]. Igazabol egy sima fifo, bar a konkret implementacio ennel joval primitivebb, sok overhead-del. De akkor teljesen jo (sot talan gyorsabb is, mint egy fifo), ha a tempbuffer merete nagysagrendileg megegyezik a sorok va'rhato' hosszaval vagy a program interaktivan reagal a bemenetre (eddig nalam mindket feltetel teljesult, azert se vacakoltam vele sokat).

A.

Nekem azert nem performancia-kritikus, mert foleg konfig fajlok olvasasasnal jonnek ilyenek elo, hogy sorszinten kene kezelni a fajlt. Ahol lehet, igyekszek kulso konyvtarakkal dolgoztatni, mert azt nalam c-hez picit (oke, sokkal) jobban erto emberek raktak ossze.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Nekem azert nem performancia-kritikus, mert foleg konfig fajlok olvasasasnal jonnek ilyenek elo, hogy sorszinten kene kezelni a fajlt.
Mondjuk ebben az esetben egy read/write + egy kezzel irt buffereles kicsit agyu-vereb kategoria. Ha pipe-ok, socket-ek, sajat protokoll, bizonytalan halozat, konkurrens olvasas/iras van, es elkerulhetetlen a read/write hasznalata az mas kerdes. Konfig file-okra a fgets azert jo szokott lenni, ott a szuk keresztmetszet inkabb a sorhossz limitaltsag. De arra legalabb vannak jo kesz megoldasok (readline(), getline()). read/write + sorbufferelesre nincs, az teny.