You are on page 1of 14

Pipe Senkronizasyonu ve modu

A
Yazıldığı Zaman :

1- Eğer yazan process dolu pipe ‘a


yazmaya çalışırsa, okuyan pipe
process bir şeyler okuyana kadar
yazan process bloke olur.

2- Pipe’a yazma işlemi atomiktir. Yazma bitene


kadar proses anahtarlama olmaz

Okunduğu Zaman :

3- Eğer okuyan process boş pipe ‘ı okumaya


kalkarsa,
a. blocking modta çalışıyorsak bloke olur yada
“0” döner(pipe yazma ucu kapanırsa).
b. Unblocking modta çalışıyorsak, hata kodu ile
döner ve sorumluluk kullanıcıdadır (döngü
içinde pipe da veri olup olmadığının testi
gerekebilir bu iş kullanıcı sorumluluğundadır).

4- Pipe’dan okuma işlemi atomiktir. Okuma bitene


kadar proses anahtarlama olmaz.

1
Pipe’tan Okuma Örneği

char buf[100];

while((count = read(p[0], buf, 100)>0)

{/* buf daki veriyi kullan */

yazma okuma
pipe
ucu ucu

P[1] 230 bytes P[0]

30 100 100

read 1
read 2 (100 bytes)
(100 bytes)

read 3
(30 bytes)
read 4

bloke olur taki pipe’a bir şeyler yazılana kadar

veya sıfıra döner (eğer pipe ‘ın yazma ucu kapandı)

2
Basit bir Örnek

User
write(fd[1], …) ; Process
read(fd[0], … ) ;
OS kernel

pipe

fd[1] fd[0]

#include <stdio.h>

main()
{ int n, fd[2] ;

char buf[128] ;

if ( pipe(fd) < 0 ) { /* hata mesajı ve exit */ }

if ( write(fd[1], “Mersin\n”, 7) != 7 )
{ /* hata mesajı ve exit */ }

if ( (n = read(fd[0], buf, sizeof(buf))) <= 0 )


{ /* hata mesajı ve exit */ }

write(1, buf, n) ; /* fd = 1 standart output */

exit(0) ; /* normal exit */


}
3
Detaylı örnek: program şeması

Process A: Pipe yaratıcısı


Standard Shell (shell)
Output
pipe

Process B: Process C:
who sort
Standard
Input

Amaç: who | sort

who processinin çıktısı , sort processinin girdisi olur.

Pipe’ın yazma ucu ile “who” processinin outputunu


(çıktısını) eşleştirmeliyiz.
Pipe’ın okuma ucu ile “sort” processinin inputunu
(girdisini) eşleştirmeliyiz.

Bu işlem aslında input/output yönlendirmeleridir.

4
Dosya Tanımlayıcılarının Kopyalanması
new_fd =dup(fd) ; /* fd tanımlayıcısını, tanımlayıcı
tabloda yeni bir ID (new_fd) ile kopyalar. */

dup2(fd1, fd2) ; /* fd2 tanımlayıcılı dosyayı kapatır ve


onu fd1 tanımlayıcı dosyaya yönlendirir*/
Sonuç: fd2 , fd1 ‘in kopyasıdır (her ikiside fd1 ‘
gösterir)

Örnek (0 yönlendiriltikten sonra eski haline getiriliyor):


1- fd0 =dup(0) /* 0 tanımlayıcısı kopyalandı*/
2- dup2(fd, 0) /* 0 , fd ‘ye yönlendirildi*/

Kullanıcı Dosya
Sistem Dosya Tablosu
Tanım. Tablosu
dup2’den  Adres A0
önce 1 .
Giriş 1 dosya1
. Giriş 0 dosya2
fd Adress A1

0 Adress A1
dup2’den
1 .
sonra
Giriş 1 dosya1
.

fd Adress A1 Giriş 0

Bu durumda doysa tanımlayıcısı 0 ‘ın kullanıldığı heryerde dosya1


referans edilir.

3- dup2(fd0, 0) /* 0 , eski haline geldi*/


4- close(fd0) /* fd0 , ile işimiz kalmadı*/
5
Hatırlatma

dup2(old, new) ; /* new kapanır ve old ‘un


gösterdiği dosyayı
gösterir*/

Örnekler:
a)

int p[2] ;
pipe(p) ; p[1] p[0]

dup2(p[1], 1) ; stdout p[0]


p[1]

/* stdout ekran yerine pipe’ı output olarak kullanır


*/

b)

int p[2] ;
pipe(p) ; p[1] p[0]
dup2(p[0], 0) ; p[1] stdin
p[0] from pipe

stdin klavye yerine pipe’dan okur

6
“who” ve “sort” pipe ile bağlanmasında program
yapısı

parent (A)

pipe(fd);
pid = fork(); pipe
reading process (C)
pipe pid = 0 (child 1)
writing process (B) pid = fork();
dup2(fd[0], 0) ;
pid = 0
close(fd[1] ;
(child 2)
execlp(“sort”, “sort”, 0) ;
dup2(fd[1], 1) ;
close(fd[0] ;
execlp(“who”, “who”, 0) ; “sort”

exit()
“who” close fd[0] ;
… close fd[1] ;
exit() wait(0) ;
wait(0) ;
exit(0) ;

fd[1] fd[0]
who sort
pipe

7
#include <stdio.h>
#include <unistd.h>
main()
{ int fd[2] ; int pid ;
pipe(fd) ;
pid = fork() ;
if ( pid == 0)
{ dup2( fd[0], 0) ; /* stdinp pipe’ın okuma ucuna bağlanır*/
close(fd[1]) ; /* yazma ucunu kapat*/
execlp(“sort”, “sort”, 0 ) ; /* “sort” u çalıştır */
}

pid = fork() ;
if (pid == 0 )
{ dup2(fd[1], 1) ; /*stdout pipe yazma ucuna bağlanır*/
close ( fd[0]) ; /* Okuma ucunu kapat */
execlp(“who”, “who”, 0) ; /* “who” çalıştır*/

close ( fd[0]) ;
close(fd[1]) ;
wait(0) ;
wait(0) ;
}

8
UNIX te Adlandırılmış Pipe

yazma okuma
pipe
Process A Process B
(FIFO)

Sistem Çağrıları:

open()
mknode()
read()
write()
close()

Örnek:
int a ;
. . .
a = mknod(pipe_adı, S_IFIFO | 0666, 0 ) ;
if ( a < 0 ) { /*Hata */ }

9
İki process için bir program:
 Process A adlandırılmış Pipe ‘ yaratır veya yazar
 Process B adlandırılmış Pipe ‘ yaratır veya okur

#include <fcntl.h>
char text[] = “mersin” ;

main(argc, argv)
int argc ; char *argv[] ;

{ int fd ; char buf[100] ;


mknode(“/tmp/abc”, S_IFIFO | 0666, 0) ; /*Pipe
yarat*/

if (argc == 2 ) fd = open(“/tmp/abc”, O_WRONLY) ;


else fd = open(“/tmp/abc”, O_RDONLY) ;
/* loop for ever */

for ( ; ; )
if ( argc == 2 ) write(fd, text, 6 ) ;
else { int n = read(fd, buf, 6) ;
buf[n]=’\0’; print (“%s\n”, buf);
}
}

Yukarıdaki programı komut satırından çalıştırma:

%<prog_adı> <kullanılmayan_bir_param> & process A için


%<prog_adı> process B için

10
Adlandırılmış Pipe ile istemci/sunucu

Sunucu UNIX
host
cevap cevap
Özel pipe 1 Özel pipe 2

Public pipe
/tmp/abc
İstemci 1 İstemci 2

istek
mesaj

11
İstemci programı (bir parçası)
#include …
struct message {
char pname[128] ;
char istek[512] ; /* sunucuya mesaj yapısı */
} ; Kullanım:
%prog_adı ozel_pipe
main ( argc, argv )
int argc ; char *argv[] ;
{ int n, public, ozel ;
struct message msg ;
char buf[PIPE_BUF] ;
msg.pname = argv[1] ;

mknod( msg.pname, … ); /*özel pipe yarat*/


public = open(“/tmp/abc”, O_WRONLY ) ;

msg.istek = … ;
write( public, &msg, sizeof(msg) ) ;

ozel = open(argv[1], O_RDONLY) ;

while ( (n = read(ozel, buf, PIPE_BUF) ) > 0 )

{sunucudan gelen cevabı kullan... }

close( ozel) ; close( public ) ; unlink( argv[1] ) ;


}

12
Sunucu programı (bir parçası)

#include …
struct message { … } ; /* istemci ile aynı */

main() /* komut satırı params YOK */


{ int n, public, ozel;
char buf[PIPE_BUF] ;
struct message msg ;

mknode(“tmp/abc”, … ) ; /* public pipe yarat */

public = open(“tmp/abc”, O_RDONLY ) ;


while ( read(public, &msg, sizeof(msg) ) > 0 )
{ …
ozel = open( msg.pname, O_WRONLY ) ;
/* buf içine bir cevap yaz ve gönder*/

write( ozel, buf, n ) ;
close( ozel ) ;
….
}
… /* isteği al ve cevap gönder */

13
Pipe Limitleri
1. Bir pipe tek-yönlüdür

2. Processler bağımlı olmalı (child process gibi): Parent


pipe yaratır ve tanımlayıcıları child’e uzatır.
3. Pipelar geçicidir (örnek. Parent process öldüğünde oda
ölür).

2 ve 3 sınırlaması adlandırılmış pipe da yoktur.

14

You might also like