Potok jest plikiem otwartym w systemie plików jądra i nie jest dostępny jako zwykły plik na dysku. Jest automatycznie buforowany tylko do określonego rozmiaru i ostatecznie zostanie zablokowany po zapełnieniu. W przeciwieństwie do plików pochodzących z urządzeń blokowych, potoki zachowują się bardzo podobnie do urządzeń znakowych, a więc ogólnie nie obsługują, lseek()
a odczytane z nich dane nie mogą być ponownie odczytane, tak jak w przypadku zwykłego pliku.
Ciąg tutaj jest zwykłym plikiem utworzonym w zamontowanym systemie plików. Powłoka tworzy plik i zachowuje swój deskryptor, jednocześnie natychmiast usuwając jedyne łącze do systemu plików (i tak usuwając), zanim zapisuje / odczytuje bajt do / z pliku. Jądro zachowa przestrzeń wymaganą dla pliku, dopóki wszystkie procesy nie zwolnią dla niego wszystkich deskryptorów. Jeśli dziecko czytające z takiego deskryptora ma taką możliwość, można je przewinąć lseek()
i przeczytać ponownie.
W obu przypadkach tokeny <<<
i |
reprezentują deskryptory plików i niekoniecznie same pliki. Możesz uzyskać lepszy obraz tego, co się dzieje, wykonując takie czynności, jak:
readlink /dev/fd/1 | cat
...lub...
ls -l <<<'' /dev/fd/*
Najistotniejsza różnica między tymi dwoma plikami polega na tym, że ciąg tutaj / dokument jest właściwie sprawą naraz - powłoka zapisuje w nim wszystkie dane przed przekazaniem deskryptora odczytu dziecku. Z drugiej strony powłoka otwiera potok na odpowiednich deskryptorach i odradza dzieciom zarządzanie tymi dla potoku - tak więc jest on zapisywany / odczytywany jednocześnie na obu końcach.
Te rozróżnienia są jednak ogólnie prawdziwe. O ile mi wiadomo (co tak naprawdę nie jest aż tak daleko), dotyczy to praktycznie każdej powłoki, która obsługuje <<<
skrót <<
tutaj do przekierowania dokumentu tutaj z jednym wyjątkiem yash
. yash
, busybox
, dash
, Oraz inne ash
warianty mają tendencję do tu-dokumentów z rur, choć i tak w tych muszli tam naprawdę jest bardzo mała różnica między nimi po wszystkim.
Ok - dwa wyjątki. Teraz, gdy o tym myślę, ksh93
tak naprawdę nie robi potoku dla |
, ale obsługuje cały biznes z gniazdami - chociaż robi usunięty plik tmp dla <<<*
większości innych. Co więcej, umieszcza tylko oddzielne sekcje potoku w środowisku podpowłoki, która jest rodzajem eufemizmu POSIX, ponieważ przynajmniej działa jak podpowłoka , a więc nawet nie robi forks.
Faktem jest, że wyniki testu porównawczego @ PSkocik (co jest bardzo przydatne) mogą się znacznie różnić z wielu powodów, a większość z nich zależy od implementacji. W przypadku konfiguracji dokumentu tutaj najważniejszymi czynnikami będą docelowy ${TMPDIR}
typ systemu plików i bieżąca konfiguracja / dostępność pamięci podręcznej, a także nadal ilość zapisywanych danych. W przypadku potoku będzie to rozmiar samego procesu powłoki, ponieważ wykonywane są kopie wymaganych widelców. W ten sposób bash
jest okropny przy ustawianiu potoków (w tym zastępowanie $(
poleceń )
) - ponieważ jest duży i bardzo wolny, ale z ksh93
tym nie robi prawie żadnej różnicy.
Oto kolejny mały fragment powłoki pokazujący, w jaki sposób powłoka dzieli podpowłoki dla potoku:
pipe_who(){ echo "$$"; sh -c 'echo "$PPID"'; }
pipe_who
pipe_who | { pipe_who | cat /dev/fd/3 -; } 3<&0
32059 #bash's pid
32059 #sh's ppid
32059 #1st subshell's $$
32111 #1st subshell sh's ppid
32059 #2cd subshell's $$
32114 #2cd subshell sh's ppid
Różnica między tym, co pipe_who()
raportuje wywołanie potokowe , a raportem z jednego uruchomienia w bieżącej powłoce wynika (
z )
określonego zachowania podpowłoki, polegającego na żądaniu pid powłoki macierzystej, $$
gdy jest ona rozwinięta. Chociaż bash
podpowłoki zdecydowanie są oddzielnymi procesami, $$
specjalny parametr powłoki nie jest wiarygodnym źródłem tych informacji. Mimo to potomna sh
skorupa podpowłoki nie odmawia dokładnego zgłoszenia jej $PPID
.