Kiedy użyłem potoku w bashu, nie myślałem o tym więcej. Ale kiedy czytam przykład kodu C za pomocą wywołania systemowego pipe () razem z fork (), zastanawiam się, jak rozumieć potoki, w tym potoki anonimowe i potoki nazwane.
Często słyszy się, że „wszystko w systemie Linux / Unix jest plikiem”. Zastanawiam się, czy potok jest tak naprawdę plikiem, więc jedna część, którą łączy, zapisuje do pliku potoku, a druga część czyta z pliku potoku? Jeśli tak, to gdzie jest tworzony plik potoku dla anonimowego potoku? W / tmp, / dev lub ...?
Jednak z przykładów nazwanych potoków dowiedziałem się również, że używanie potoków ma przewagę nad przestrzenią i czasem w porównaniu z jawnym używaniem plików tymczasowych, prawdopodobnie dlatego, że nie ma żadnych plików zaangażowanych w implementację potoków. Także potoki wydają się nie przechowywać danych tak jak pliki. Więc wątpię, czy potok jest właściwie plikiem.
Jeśli chodzi o twoje pytanie dotyczące wydajności, potoki są bardziej wydajne niż pliki, ponieważ nie jest potrzebne IO dysku. cmd1 | cmd2Jest to więc bardziej wydajne niż cmd1 > tmpfile; cmd2 < tmpfile(może nie być to prawdą, jeśli tmpfilejest ono zapisane na dysku RAM lub innym urządzeniu pamięci jako nazwany potok; ale jeśli jest to nazwany potok, cmd1należy go uruchomić w tle, ponieważ jego wyjście może blokować, jeśli potok się zapełni ). Jeśli potrzebujesz wyniku cmd1i nadal musisz wysłać jego dane wyjściowe cmd2, powinieneś cmd1 | tee tmpfile | cmd2pozwolić cmd1i cmd2uruchomić równolegle, unikając operacji odczytu dysku cmd2.
Nazwane potoki są przydatne, jeśli wiele procesów odczytuje / zapisuje ten sam potok. Mogą być również użyteczne, gdy program nie jest zaprojektowany do używania stdin / stdout dla swoich operacji we / wy potrzebujących plików . Umieszczam pliki kursywą, ponieważ nazwane potoki nie są dokładnie plikami z punktu widzenia przechowywania, ponieważ znajdują się w pamięci i mają stały rozmiar bufora, nawet jeśli mają wpis systemu plików (w celach informacyjnych). Inne rzeczy w systemie UNIX mają wpisy w systemie plików, nie będąc plikami: pomyśl tylko o /dev/nullinnych wpisach w /devlub /proc.
Ponieważ potoki (nazwane i nienazwane) mają ustalony rozmiar bufora, operacje odczytu / zapisu na nich mogą blokować, powodując przejście procesu odczytu / zapisu w stan IOWait. Ponadto, kiedy otrzymasz EOF podczas odczytu z bufora pamięci? Zasady dotyczące tego zachowania są dobrze określone i można je znaleźć u mężczyzny.
Jedną rzeczą, której nie można zrobić z potokami (nazwanymi i nienazwanymi), jest wyszukiwanie danych. Ponieważ są one realizowane za pomocą bufora pamięci, jest to zrozumiałe.
O "everything in Linux/Unix is a file"nie zgadzam się. Nazwane potoki mają wpisy w systemie plików, ale nie są dokładnie plikami. Potoki nienazwane nie mają wpisów w systemie plików (z wyjątkiem być może in /proc). Jednak większość operacji we / wy w systemie UNIX jest wykonywana przy użyciu funkcji odczytu / zapisu, która wymaga deskryptora pliku , w tym potoku bez nazwy (i gniazda). Nie sądzę, że możemy to powiedzieć "everything in Linux/Unix is a file", ale z pewnością możemy to powiedzieć "most IO in Linux/Unix is done using a file descriptor".
Dzięki! Czy te dwa polecenia są połączone równolegle działającą rurą, a nie druga zaczyna działać po pierwszym zakończeniu?
Tim
Tak, 2 polecenia są uruchamiane równolegle. Gdyby nie były, a 1. wyjście więcej niż bufor, byłoby zablokowane. Można spróbować go uruchamiając cmd1 > fifoi cmd2 < fifow 2 różnych skorup, tworząc z nazwanego potoku mkfifo fifo.
jfg956
Kolejnym testem, jaki możesz wykonać, jest zabicie, cmd2gdy cmd1jest jeszcze uruchomiony: cmd1prawdopodobnie przestanie zgłaszać zepsuty komunikat dotyczący potoku.
jfg956,
Dzięki! co masz na myśli, że zostanie zablokowany? Jeśli tak się stanie, czy oznacza to, że data w strumieniu po bloku zostanie utracona?
Tim
2
Dane nie są tracone. Jeśli bufor potoku jest pełny, cmd1zapis do potoku zostanie zwrócony tylko wtedy cmd2, gdy będzie miał odczyt danych z potoku. W ten sam sposób cmd2odczyt z potoku zostanie zablokowany, jeśli bufor będzie pusty, dopóki nie zostanie cmd1zapisany w potoku.
jfg956
4
Dwie podstawowe podstawy filozofii UNIX to
Aby tworzyć małe programy, które robią jedną rzecz dobrze.
i oczekuj, że wyjście każdego programu stanie się wejściem do innego,
jeszcze nieznanego, programu.
Zastosowanie rur pozwala wykorzystać efekty tych dwóch
podstaw projektowania, aby stworzyć niezwykle potężne łańcuchy poleceń, aby osiągnąć pożądany rezultat.
Większość programów wiersza polecenia, które działają na plikach, może również akceptować wejście standardowego wejścia (wejście za pomocą klawiatury) i wyjście standardowego wyjścia (drukowanie na
ekranie).
Niektóre polecenia są zaprojektowane do działania tylko w obrębie potoku i nie mogą działać bezpośrednio na plikach.
na przykład trpolecenie
ls -C | tr 'a-z''A-Z'
cmd1 | cmd2
Wysyła STDOUT z cmd1 do STDIN z cmd2 zamiast ekranu.
STDERR nie jest przekazywany między rurami.
W skrócie Pipes is character (|)można połączyć polecenia.
Każde polecenie, które zapisuje do STDOUT, może być użyte po lewej stronie potoku.
ls -/etc | less
Każde polecenie, które czyta ze STDIN, może być użyte po prawej stronie potoku.
echo "test print"| lpr
Tradycyjny potok jest „nienazwany”, ponieważ istnieje anonimowo i trwa tylko tak długo, jak trwa proces. Nazwany potok jest trwały dla systemu i istnieje po zakończeniu procesu i musi zostać usunięty, gdy nie będzie już używany. Procesy zazwyczaj dołączają się do nazwanego potoku (zwykle pojawiającego się jako plik) w celu wykonania komunikacji międzyprocesowej (IPC).
stdin i stdout są deskryptorami plików i są odczytywane i zapisywane tak, jakby były plikami. dlatego możesz to zrobić echo hi | grep hi, a to zastąpi stdout echa rurą i zastąpi stdin grep na drugim końcu tej rury.
Jeśli użyjemy tego wyrażenia zbyt dosłownie, otrzymamy znaczenie „mamy tylko pliki i nic więcej”. To nie jest poprawna interpretacja, więc co jest.
Kiedy mówimy „Wszystko jest plikiem”, nie mówimy, że wszystko jest przechowywane na dysku. Mówimy, że wszystko wygląda jak plik, można je odczytać, można zapisać.
W Uniksie po otwarciu pliku lub pliku innego niż plik można go traktować jak plik. Jednak nie wszystkie pliki obsługują wszystkie operacje. Np. Niektóre pliki (które nie są plikami) nie obsługują przeszukiwania: muszą być odczytywane / zapisywane w sekwencji (dotyczy to potoków i gniazd).
Wszystko ma nazwę pliku (w niektórych systemach: np. Debian Gnu / Linux i wielu innych Gnu / Linux).
Wszystkie otwarte pliki otrzymują nazwę pliku. Widzieć/proc/self/fd/…
Gniazda sieciowe można otworzyć za pomocą nazwy pliku, patrz /dev/tcp
npcat </dev/tcp/towel.blinkenlights.nl/23
cmd1 > fifo
icmd2 < fifo
w 2 różnych skorup, tworząc z nazwanego potokumkfifo fifo
.cmd2
gdycmd1
jest jeszcze uruchomiony:cmd1
prawdopodobnie przestanie zgłaszać zepsuty komunikat dotyczący potoku.cmd1
zapis do potoku zostanie zwrócony tylko wtedycmd2
, gdy będzie miał odczyt danych z potoku. W ten sam sposóbcmd2
odczyt z potoku zostanie zablokowany, jeśli bufor będzie pusty, dopóki nie zostaniecmd1
zapisany w potoku.Dwie podstawowe podstawy filozofii UNIX to
i oczekuj, że wyjście każdego programu stanie się wejściem do innego,
jeszcze nieznanego, programu.
Zastosowanie rur pozwala wykorzystać efekty tych dwóch
podstaw projektowania, aby stworzyć niezwykle potężne łańcuchy poleceń, aby osiągnąć pożądany rezultat.
Większość programów wiersza polecenia, które działają na plikach, może również akceptować wejście standardowego wejścia (wejście za pomocą klawiatury) i wyjście standardowego wyjścia (drukowanie na
ekranie).
Niektóre polecenia są zaprojektowane do działania tylko w obrębie potoku i nie mogą działać bezpośrednio na plikach.
na przykład
tr
polecenieWysyła STDOUT z cmd1 do STDIN z cmd2 zamiast ekranu.
STDERR nie jest przekazywany między rurami.
W skrócie
Pipes is character (|)
można połączyć polecenia.Każde polecenie, które zapisuje do STDOUT, może być użyte po lewej stronie potoku.
Każde polecenie, które czyta ze STDIN, może być użyte po prawej stronie potoku.
Tradycyjny potok jest „nienazwany”, ponieważ istnieje anonimowo i trwa tylko tak długo, jak trwa proces. Nazwany potok jest trwały dla systemu i istnieje po zakończeniu procesu i musi zostać usunięty, gdy nie będzie już używany. Procesy zazwyczaj dołączają się do nazwanego potoku (zwykle pojawiającego się jako plik) w celu wykonania komunikacji międzyprocesowej (IPC).
źródło: http://en.wikipedia.org/wiki/Named_pipe
źródło
Aby uzupełnić inne odpowiedzi ...
stdin i stdout są deskryptorami plików i są odczytywane i zapisywane tak, jakby były plikami. dlatego możesz to zrobić
echo hi | grep hi
, a to zastąpi stdout echa rurą i zastąpi stdin grep na drugim końcu tej rury.źródło
Wszystko jest plikiem.
Jeśli użyjemy tego wyrażenia zbyt dosłownie, otrzymamy znaczenie „mamy tylko pliki i nic więcej”. To nie jest poprawna interpretacja, więc co jest.
Kiedy mówimy „Wszystko jest plikiem”, nie mówimy, że wszystko jest przechowywane na dysku. Mówimy, że wszystko wygląda jak plik, można je odczytać, można zapisać.
W Uniksie po otwarciu pliku lub pliku innego niż plik można go traktować jak plik. Jednak nie wszystkie pliki obsługują wszystkie operacje. Np. Niektóre pliki (które nie są plikami) nie obsługują przeszukiwania: muszą być odczytywane / zapisywane w sekwencji (dotyczy to potoków i gniazd).
Wszystko ma nazwę pliku (w niektórych systemach: np. Debian Gnu / Linux i wielu innych Gnu / Linux).
/proc/self/fd/…
/dev/tcp
np
cat </dev/tcp/towel.blinkenlights.nl/23
źródło
/proc
plików oraz w systemach (lub powłokach), które zapewniają/dev/tcp
strukturę plików.