Jak rozumieć rury


21

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.

Odpowiedzi:


23

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

  1. Aby tworzyć małe programy, które robią jedną rzecz dobrze.
  2. 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).

źródło: http://en.wikipedia.org/wiki/Named_pipe


3

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.


1

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).

  • 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

Ta ostatnia część jest ważna tylko w systemach z systemem /procplików oraz w systemach (lub powłokach), które zapewniają /dev/tcpstrukturę plików.
Kusalananda
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.