[linux-programlama] Re: dup ve pipe.

---------

From: Serdar KÖYLÜ (skoylu@gizemcafe.net)
Date: Wed 27 Aug 2003 - 11:33:00 EDT

  • Next message: Orhan Sümer: "[linux-programlama] Re: Apache + Tomcat class calsitirma sorunu"

    Selamlar..

    Soru biraz karisik.. Pek bir sey anlamadim ama sunlari soyleyeyim..

    pipe'in aldigi iki fd, birisi stdin (0), digeri stdout(1). Birde orada
    goremediginiz ama her zaman kullanabileceginiz stderr var.=20

    Tamam bunu biliyoruz. Ama envelope stdout'tan nasil aliniyor ? Sanirim
    kodu yorumlamaniz biraz yanlis. Dahasi, execve ile programi
    calistirmissaniz, sizin child'iniz yok olacak, yeni program
    calisacaktir. Sizin stdout'unuz kapatmanizla, dup() kullanarak bunu
    child'e redirect etmeniz mumkundur. Biraz karisik oldu biliyorum.
    Ornegin su sekilde:

    #include <sys/types.h>
    #include <unistd.h>

    #define STDIN 0
    #define STDOUT 1

    int main(void)
    {
    . char *process=3D"/ivir/zivir/qmail-original";
    . int fd[2];
    . /* pipe file desc.leri bunlar pipe icin kullanilacak. */
    . pipe(fd);
    . if( fork() !=3D 0 ) { /* Bizim programimiz (parent) */
    . close(fd[0]); /* Biz artik okuyamayiz pipe'den */
    . close(STDOUT); /* stdout'u kapatinca,=20
    . bu pipe icin hazirlanmis olur */
    . dup(fd[1]); /* stdout pipe'a yazacak bu hamleyle */
    . close(fd[1]); /* Bu bize lazim degil. Extra fd.. */
    . execl( process, process, 0 );=20
    . } else {
    . /* Burasi child. */
    . close(fd[1]); /* Bu parentinkiyle ayni dosya.
    . Buna yazmamaliyiz. */
    . close(STDIN); /* Child'in stdin'i kapatalim ki
    . bu redirect edilsin. */
    . dup(fd[0]); /* stdin, artik pipe'tan okunacak. */
    . close(fd[0]); /* Bu da ekstra fd. */
    . }
    . printf("Bu mesaj %s ye yazilacak\n", "child process'e");
    . return 0;
    }

    Tamam bu birazcik alisilmisin disinda oldu. Child yerinde duruyor,
    parent'e yaziyor. Attraksiyon iyidir :))

    Ama sanirim dup()'un ne zaman nasil kullanilacagini anlatiyordur. Eger
    pipe fd'leri ve stdin/stdout (her zaman 0/1 numarali dosyalar) aciksa,
    sizin pipe'iniz redirection icin kullanilamaz. stdout'u kapatip, fd[1]'i
    dup edince, pipe fd'niz (fd[1]) stdout yerini alir. stdout'a tum
    yazilanlar boruya akar.=20

    Sizin kodda, close()'lar kullanilmamis. Bu yuzden stdin ve stdout ortada
    oluyor. pipe sadece kendi descriptorlari uzerinden calisiyor. PIPE
    mekanizmasini fork()'tan ayrik dusunmeyin. Simdi bir borunuz var. bir
    ucundan yazilan obur ucundan cikiyor. fork() sonrasi her iki ucta her
    iki programda da mevcut bu fd[]. Yani child boruya yazarsa, hem
    child'deki fd[0]'den, hemde parent'teki fd[0]'den okunabilir. Bunlar
    ayni boru. Ama fd[] her iki tarafta farkli degisken ama.=20

    Siz bunlarin diger tarafa ait olan ucunu kapatmazsiniz is karisir.
    Ayrica pipe'lar otomatik olarak stdin/stdout'a baglanmaz. Yukaridaki
    gibi bir ornek yazmanin esprisi, full-duplex pipe olusturmak icin iki
    tane pipe nasil kullaniriz buna bir ornekte teskil etmek. Yani sizin
    parent->child borunuzun yaninda, child->parent borunuzunda olmasi
    gerekiyor.=20

    STDIN bir dosyadir. Sizin sureciniz icin aciktir. close() ile kapatinca
    kapanir ve sizin childiniz dup() ile elde ettiginiz stdin'den okur. Kara
    buyu yok burada. dup() her zaman en kucuk file handleri dondurur. siz
    close() ile STDIN'i (=3D0) kapatirsaniz, dup(fd[0]), fd[0]'in (borunun
    ucunu) 0 nolu handle (hah, oda stdin'di) olarak yeni bir handle (file
    descriptor) olusturur. child, bu noktadan sonra stdin'den okumak
    istedigi surece borudan okur ve farkina varmaz. Puf noktasi, stdin'i
    kapatinca kullanilmayan en kucuk file descriptor (handle) 0 olacaktir.
    Hemen ardindan gelen dup(), yeni file descriptor olarak 0'i
    kullanacaktir. Puf noktasini anladiniz umarim. Ayni durum stdout icinde
    gecerli elbette.=20

    Genelde yapilan yanlis, foksiyonlarin puf noktalarina dikkat etmemektir.
    Sorsam, cogu dup() icin sunu soyler Copy & Paste from man page:

    dup and dup2 create a copy of the file descriptor oldfd.

    Oysa devamina, 1-2 paragraf asagiya bakarsaniz asil puf noktasini
    gorursunuz:

    dup uses the lowest___numbered unused descriptor for the new descriptor.

    Siz STDIN'i kapatirsaniz ilk unused fd STDIN olur. Aslinda cok basit
    degil mi ? Demekki dup() fonksiyonu icin aslinda:

    verilen fd'nin, programda kullanilmayan en kucuk numarali fd'ye esit
    olmak uzere, yeni bir birebir kopyasini olusturur.=20

    Gibi bir sey yani.. Dilim pek donmuyor :((

    Saygi ve sevgiler..

    On Tue, 26 Aug 2003 02:31:31 +0300
    Halil Demirezen <halild@bilmuh.ege.edu.tr> wrote:

    > Selamlar,
    > mesela, ornek=20
    >=20
    > int fd[2];
    > int pid;
    >=20
    > if(pipe(fd) !=3D 0)
    > perror("pipe fail"), exit(-1);
    >=20
    >=20
    > if((pid =3D fork()) !=3D 0)
    > write(fd[1], "deneme msg", 11);
    > else {
    > execve("/usr/sbin/qmail-queue-original","qmail-queue-original",
    > 0,0);
    > }
    > yukarida child icinde ben gercek qmail-queue yi calistiriyorum. ve=20
    > qmail-queue-original a 0 dan data aktamam gerekiyor. ve bunu
    > kesinlikle yani 0 inci fd yi kesinlikle fd[0] ile iliskilendirmem
    > gerekiyor ki parent te fd[1] e yazilan bir data pipe araciligi ile
    > fd[0] a aktarilmali ve ayni zamanda fd[0], 0 oldugu icin calisan
    > programin 0. fd. sinden input olarak alinmali...
    >=20
    > bunun dup ve dup2 syscall larla yapilacagini bir yerde okudum
    >=20
    > close(0);
    > dup2(0, fd[0]);


  • Next message: Orhan Sümer: "[linux-programlama] Re: Apache + Tomcat class calsitirma sorunu"

    ---------

    Bu arsiv hypermail 2.1.6 tarafindan uretilmistir.