next up previous contents
Next: Tworzenie potoków w C Up: Jednokierunkowe potoki z Unixa Previous: Jednokierunkowe potoki z Unixa   Contents

Podstawy

Najprościej, potok jest metodą przekierowywania standardowego wyjścia jednego procesu na standardowe wejście innego. Potoki są najstarszym narzędziem IPC, istnieją od najwcześniejszych wersji systemu operacyjnego UNIX. Są szeroko używane, nawet w linii poleceń powłoki.


\begin{tscreen}
   \begin{verbatim}ls \vert sort \vert lp\end{verbatim}\par\end{tscreen}

Powyższy przykład pokazuje zbiór potoków; przetworzenie wyjścia ls na wejście programu sort, a póżniejsze użycie wyjścia sort jako wejście lp. Dane przemieszczają się w jednokierunkowym potoku, wizualnie od lewej do prawej.

Aczkolwiek z zamiłowaniem używamy potoków w różnych skryptach, rzadko zadajemy sobie pytanie co się dzieje na poziomie jądra.

Kiedy proces tworzy potok, jądro tworzy dwa deskryptory na jego użytek. Jeden umożliwia zapis do potoku, drugi czytanie z niego. Na tym poziomie, potoki są mało użyteczne, gdyż tylko proces tworzący potok może z niego czytać. Oto reprezentacja procesu i jądra po utworzeniu potoku:

\includegraphics{pipe1.epsi}

Z powyższego rysunku łatwo można dostrzec jak deskryptory są połączone nawzajem. Jeżeli proces wysyła dane poprzez potok ( fd0 ), może je otrzymać z fd1. Jest to bardziej złożony proces, niż widać na rysunku. Gdy proces tworzy potok, a póżniej podczas przekazywania danych informacje przepływają przez jądro. Pod Linuxem, potoki są obecnie prezentowane wewnętrznie jako prawidłowe i-węzły ( inodes ). Oczywiście taki i-węzeł przebywa wewnątrz jądra, nie na jakimś fizycznym systemie plików. Takie podejście otwiera nam ładną, poręczną furtkę We/Wy, o czym przekonamy się póżniej.

Na razie potoki są daleko bezurzyteczne. Po co zadawać sobie trud tworzenia potoku aby porozmawiać ze sobą? Najczęściej proces tworzący potok tworzy ( forkuje ;) proces potomny. Proces potomny odziedzicza po rodzicu wszelkie otwarte deskryptory plików, mamy teraz podstawy aby komunikować się między procesami. Oto uaktualniony diagram:

\includegraphics{pipe2.epsi}

Widzimy, iż oba procesy mają dostęp do deskryptorów plików, które tworzą potok. Na tym poziomie musimy podjąć krytyczną decyzję: w jakim kierunku będą przesyłane dane? Po wybraniu kierunku procesy zamykają końcówkę potoku, z której nie będą korzystać. Przyjmijmy, że potomek przeprowadza jakąś akcję i wywsyła wynik poprzez potok do rodzica. Oto nasz nowy rysunek:

\includegraphics{pipe3.epsi}

Konstrukcja potoku jest gotowa! Jedyne co musimy teraz zrobić to użyć potoku. Aby tego dokonać bezpośrednio możemy używać tych samych wywołań systemowych, które istnieją do niskopoziomowego dostępu We/Wy do plików ( pamiętaj, że potoki obecnie prezentowane są jako normalne i-węzły )

Aby wysłać dane do potoku używamy wywołania systemowego write(), natomiast aby odczytać dane musimy posłużyć się wywołaniem read(). Pamiętaj, że niskopoziomowe We/Wy do pliku działa z jego deskryptorem! Jednocześnie musisz sobie zdawać sprawę, że niektóre wywołania systemowe, takie jak lseek(), nie działają z deskryptorami potoków.


next up previous contents
Next: Tworzenie potoków w C Up: Jednokierunkowe potoki z Unixa Previous: Jednokierunkowe potoki z Unixa   Contents

2000-03-01


Poltronic