popen, pclose fonksiyonları kendi içlerinde aşağı seviyeli pipe fonksiyonlarını kullanırlar.
Aşağı seviyeli pipe açmak için pipe fonksiyonu kullanılır. Bu fonksiyonun prototipi unistd.h
dosyası içerisindedir.
int pipe(int filedes[2]);
Anahtar notlar: C’de prototipte ya da tanımlama sırasında parametre parantezi içerisinde
yazılan aşağıdaki ifadeler eş değerdir.
1) void Func(int a[size]);
void Func(int *a);
C ve Sistem Programcıları Derneği 103
Burada [] içerisi boş bırakılabilir.
2) void Func(int a[RowSize][ColSize]);
void Func(int (*a) [ColSize]);
3) void Func(int f(void));
void Func(int (*f)(void));
4) void Func(int *a[10]);
void Func(int **a);
5) void Func(int a[][])
Geçersiz
pipe fonksiyonu iki elemanlı bir dizinin başlangıç adresini alır ve bir pipe oluşturarak okuma
ve yazma için gerekli olan dosya betimleyicilerini bu diziye yerleştirir. Fonksiyon başarılıysa
0, başarısızsa –1 değerine geri döner. UNIX sistemlerinde pipe’lar tıpkı dosyalar gibi işlem
görür. pipe fonksiyonundan iki dosya betimleyicisi elde edilir. Biri pipe’ı okumak için diğeri
yazmak için kullanılır. Dizinin ilk elemanına yerleştirilen betimleyici okumak için ikinci
elemanına yerleştirilen betimleyici yazmak için kullanılır. Pipe’lar POSIX standartlarında tek
yönlüdür. Yani aslında modern sistemlerin çoğunda her iki betimleyiciyle de okuma ve yazma
yapılabilmektedir. Bir pipe’a birden fazla process yazma yapabilir ve birden fazla process
pipe’tan okuma yapabilir. Pipe açıldıktan sonra klasik olarak read ve write fonksiyonlarıyla
okuma ve yazma yapılabilir.
Normal olarak blokeli modda pipe’ı okuyan process’ler aşağıdaki gibi bir döngü içerisinde
okuma işlemlerini yaparlar.
while (read(...) > 0) {
// ...
}
Burada eğer pipe’a yazma yapan hiçbir process kalmamışsa read fonksiyonu 0 ile geri döner
ve döngüden çıkılır. Örneğin, pipe’ta halen 5 byte bulunuyor olsun. pipe’a yazma yapan
process pipe’ı kapatmış olsun. Bir process’in bu pipe’dan 10 byte okumak istediğini
düşünelim. Okuyan process önce 5 byte’ı okur ve read 5 değeri ile geri döner, bir sonraki
çağırmada okuyan process bilgi okuyamaz ve 0 ile geri döner. Görüldüğü gibi pipe’a yazan
process kalmaması durumu adeta EOF etkisi yaratmaktadır.
En normal durum önce pipe’a yazma yapan process’in pipe’ı kapatması durumudur. Ancak
bunun tersi olursa, yani önce okuma yapan process pipe’ı kapatırsa write işlemi sırasında
SIGPIPE signal’i oluşur. Bu signal’in default davranışı process’in sonlanması biçimindedir.
pipe fonksiyonu ile yaratılan pipe’lara isimsiz pipe’lar denir. İsimsiz pipe’lar şöyle bir
senaryo ile kullanılabilirler: Program önce pipe fonksiyonu ile pipe’ı yaratır. Sonra fork
yapar. Böylece haberleşme üst ve alt process’ler arasında yapılır. Klasik olarak okuma
yapacak process yazma yapılan betimleyiciyi kapatır, yazma yapacak process ise okuma için
gerekli olan betimleyiciyi kapatır.
/* pipe2.c */
C ve Sistem Programcıları Derneği 104
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int pipedes[2];
pid_t pid;
char s[100];
if (pipe(pipedes) < 0) {
fprintf(stderr, "Cannot create pipe\n");
exit(1);
}
if ((pid = fork()) == -1) {
fprintf(stderr, "Cannot create pipe\n");
exit(1);
}
if (pid > 0) {
close(pipedes[0]);
write(pipedes[1], "Merhaba pipe", 13);
close(pipedes[1]);
wait(NULL);
exit(0);
}
else {
close(pipedes[1]);
read(pipedes[0], s, 13);
puts(s);
close(pipedes[0]);
exit(0);
}
return 0;
}
Sınıf çalışması: Bir pipe açınız, sonra fork işlemi yapınız. fork işleminden sonra aşağıdaki
gibi alt process’in stdin’ini pipe’a yönlendiriniz.
dup2(filedes[0], STDIN_FILENO);
Bundan sonra alt process'te exec uygulayarak wc programını çalıştırınız. Üst process’te pipe’a
bir takım yazılar yazınız. Bundan sonra üst process pipe’ı kapatarak wait fonksiyonu ile alt
process’i beklemelidir.
/*pipe3.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int pipedes[2];
pid_t pid;
char s[100];
if (pipe(pipedes) < 0) {
fprintf(stderr, "Cannot create pipe\n");
C ve Sistem Programcıları Derneği 105
exit(1);
}
if ((pid = fork()) == -1) {
fprintf(stderr, "Cannot create pipe\n");
exit(1);
}
if (pid > 0) {
close(pipedes[0]);
write(pipedes[1], "Selamlar", 10);
close(pipedes[1]);
wait(NULL);
exit(0);
}
else {
close(pipedes[1]);
dup2(pipedes[0], STDIN_FILENO);
execlp("wc", "wc", (char *) 0);
}
return 0;
}
/* pipe4.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
FILE *f;
int i;
if ((f = popen("wc", "w")) == NULL) {
fprintf(stderr, "Cannot open pipe!...\n");
exit(1);
}
for (i = 0; i < 100; ++i)
fprintf(f, "sayi = %d\n", i);
pclose(f);
return 0;
}