Po co używać nazwanego potoku zamiast pliku?

42

Ostatnio czytałem o nazwanych potokach i nie mogłem zrozumieć, dlaczego one istnieją.
Czytałem gdzieś, że użycie nazwanego potoku jest mniej czasochłonne niż użycie pliku.

Dlaczego tak jest?
Nazwane potoki również muszą być przechowywane w pamięci (i być może wymieniane, tak jak pliki).
O ile widzę, muszą uzyskać i-węzeł, do którego musi odwoływać się bieżący katalog, podobnie jak pliki. Ponadto muszą zostać usunięte przez programistę, podobnie jak pliki.

Więc gdzie leży przewaga?

użytkownik3122885
źródło
To nie jest część zadania w klasie, prawda?
don.joey
6
nie ... właściwie przeglądałem notatki z wykładów, kiedy znalazłem to pytanie i nie mogłem na nie odpowiedzieć ... a jeśli byłoby to zadanie, nie rozumiem, jak by to miało znaczenie ... to nie jest tak Nie szukałem odpowiedzi, dopóki jej nie znajdę
user3122885

Odpowiedzi:

41

Prawie wszystko w Linuksie można uznać za plik , ale główna różnica między zwykłym plikiem a nazwanym potokiem polega na tym, że nazwany potok jest specjalną instancją pliku, który nie ma zawartości w systemie plików.

Oto cytat z man fifo:

Plik specjalny FIFO (nazwany potok) jest podobny do potoku, z tym że jest dostępny jako część systemu plików. Można go otworzyć za pomocą wielu procesów odczytu lub zapisu. Kiedy procesy wymieniają dane za pośrednictwem FIFO, jądro przekazuje wszystkie dane wewnętrznie bez zapisywania ich w systemie plików. Tak więc plik specjalny FIFO nie ma zawartości w systemie plików; pozycja systemu plików służy jedynie jako punkt odniesienia, dzięki czemu procesy mogą uzyskać dostęp do potoku przy użyciu nazwy w systemie plików.

Jądro utrzymuje dokładnie jeden obiekt potoku dla każdego pliku specjalnego FIFO, który jest otwierany przez co najmniej jeden proces. FIFO musi zostać otwarte na obu końcach (odczyt i zapis) przed przekazaniem danych. Zwykle otwieranie bloków FIFO aż do otwarcia drugiego końca również.

Tak więc nazwany potok nic nie robi, dopóki jakiś proces go nie odczyta i nie zapisze. Nie zajmuje miejsca na dysku twardym (poza odrobiną meta informacji), nie wykorzystuje procesora.

Możesz to sprawdzić, wykonując następujące czynności:

Utwórz nazwaną potok

$ mkfifo /tmp/testpipe

Przejdź na przykład do jakiegoś katalogu /home/user/Documentsi gzip wszystko w nim, używając nazwanego potoku.

$ cd /home/user/Documents
$ tar cvf - . | gzip > /tmp/testpipe &
[1] 28584

Tutaj powinieneś zobaczyć PID procesu gzip. W naszym przykładzie było to 28584.

Teraz sprawdź, co robi ten PID

$ ps u -P 28584
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
c0rp     28584  0.0  0.0  29276  7800 pts/8    S    00:08   0:00 bash

Zobaczysz, że nie używa żadnych zasobów . 0% zużycie procesora, 0% zużycie pamięci.

Sprawdź przeczucie dotyczące wykorzystania przestrzeni plików

$ du -h /tmp/testpipe
0   testpipe

I znowu 0nic. W razie potrzeby można użyć rurki testowej.

Nie zapomnij zabić gzipa, używając kill -15 28584. I usuń naszą nazwaną potok za pomocąrm /tmp/testpipe

Przykładowe zastosowania

Możesz przekierować prawie wszystko za pomocą nazwanego potoku. Jako przykład możesz zobaczyć ten jednokreskowy serwer proxy .

Również tutaj jest jeszcze jeden miły wyjaśnienie nazwie użytkowania rur. Możesz skonfigurować dwa procesy na jednym serwerze, aby komunikowały się przy użyciu nazwanego potoku zamiast stosu TCP / IP. Jest znacznie szybszy i nie ładuje zasobów sieciowych. Na przykład Twój serwer internetowy może komunikować się z bazą danych bezpośrednio za pomocą nazwanego potoku, zamiast używać localhostadresu lub nasłuchiwać na jakimś porcie.

c0rp
źródło
14

To prawda, że ​​nie użyjesz pamięci systemowej, ale fakt, że nie używasz procesora w twoim przykładzie, wynika tylko z tego, że nie czytasz potoku, więc proces czeka.

Rozważ następujący przykład:

mkfifo /tmp/testpipe
tar cvf - / | gzip > /tmp/testpipe

Teraz otwórz nową konsolę i uruchom:

watch -n 1 'ps u -P $(pidof tar)

I w trzeciej konsoli:

cat /tmp/testpipe > /dev/null

Jeśli spojrzysz na zegarek cmd (2. kadencja), pokaże on wzrost zużycia procesora!

GARCIN David
źródło
1
Ta odpowiedź dotyczy odpowiedzi
c0rp
2

Oto przykład zastosowania, w którym nazwane potoki mogą zaoszczędzić dużo czasu, usuwając We / Wy.

Załóżmy, że masz plik BigFile, na przykład 10G.

Masz również podziały tego BigFile na kawałki 1G, BigFileSplit_01 na BigFile_Split_10.

Teraz masz wątpliwości co do poprawności BigFileSplit_05

Naiwnie, bez nazwanych potoków, utworzyłbyś nowy podział z BigFile i porównałbyś:

dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

Z nazwanymi potokami zrobiłbyś

mkfifo BigFileSplitOrig_05
dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1 &
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

Na pierwszy rzut oka może to nie wydawać się dużą różnicą ... ale z czasem różnica jest ogromna!

Opcja 1:

  • dd: odczyt 1G / zapis 1G (1)
  • diff: przeczytaj 2G
  • rm: wolne przydzielone klastry / usuń pozycję katalogu

Opcja 2:

  • dd: nic! (idzie do nazwanego potoku)
  • diff: przeczytaj 2G
  • rm: brak przydzielonego klastra do zarządzania (tak naprawdę nic nie napisaliśmy do systemu plików) / usuń pozycję katalogu

Więc w zasadzie nazwany potok oszczędza ci tutaj odczytu i zapisu 1G oraz czyszczenia systemu plików (ponieważ nie napisaliśmy nic do systemu plików oprócz pustego węzła fifo).

Brak robienia operacji we / wy, zwłaszcza zapisów, jest również dobry, aby uniknąć zużycia dysków. Jest to jeszcze bardziej interesujące, gdy pracujesz z dyskami SSD, ponieważ mają one ograniczoną liczbę zapisów przed śmiercią komórek.

(1) Oczywiście inną opcją byłoby utworzenie tego pliku tymczasowego do pamięci RAM, na przykład jeśli / tmp jest zamontowany w pamięci RAM (tmpfs). Niemniej jednak byłbyś ograniczony rozmiarem dysku RAM, podczas gdy „sztuczka z nazwaną potokiem” nie ma granic.

Zakhar
źródło
0

Możesz pozwolić programowi stać w miejscu i słuchać nazwanego potoku dla jakiegoś zdarzenia zewnętrznego. Gdy tylko wystąpi zdarzenie zewnętrzne (np. Pojawienie się nowych danych), może to zostać wykryte przez inny program, który z kolei otwiera potok do zapisu, zapisując odpowiednie dane zdarzenia na potoku. Po wydaniu instrukcji close program nasłuchujący otrzyma strumień danych przez potok za pośrednictwem instrukcji read i jest gotowy do przetworzenia tego, co ma. Nie zapomnij o zamknięciu potoku po przeczytaniu treści. Program nasłuchujący może również zwracać wyniki przetwarzania za pośrednictwem tego samego lub innego nazwanego potoku. Taka komunikacja między programami jest czasami bardzo wygodna.

Per Anton Ronning
źródło