From: Serdar KÖYLÜ (skoylu@gizemcafe.net)
Date: Wed 27 Aug 2003 - 11:33:00 EDT
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]);