Właśnie uruchomiłem kilka poleceń w terminalu i zacząłem się zastanawiać, czy Unix / Linux używa skrótów podczas uruchamiania poleceń potokowych?
Załóżmy na przykład, że mam plik zawierający milion wierszy, z których pierwsze 10 zawiera hello world
. Jeśli uruchomisz polecenie, grep "hello world" file | head
czy pierwsze polecenie zatrzyma się, gdy tylko znajdzie 10 wierszy, czy też najpierw przeszuka cały plik?
command-line
pipe
utilities
efficiency
DisgruntledGoat
źródło
źródło
-m
argument.Odpowiedzi:
Raczej. Powłoka nie ma pojęcia, co zrobią uruchomione polecenia, po prostu łączy dane wyjściowe jednego z danymi wejściowymi drugiego.
Jeśli
grep
znajdzie więcej niż 10 wierszy z napisem „hello world”, wówczashead
będzie mieć wszystkie 10 wierszy, które chce, i zamknie potok. Spowoduje togrep
zabicie SIGPIPE, więc nie trzeba kontynuować skanowania bardzo dużego pliku.źródło
grep
że nadal wysyłam dane wyjściowe do pustki, podobnie jak/dev/null
Gdy program próbuje zapisać do potoku, a proces nie odczytuje z tego potoku, program piszący odbiera sygnał SIGPIPE . Domyślnym działaniem, gdy program odbierze SIGPIPE, jest zakończenie programu. Program może zignorować sygnał SIGPIPE, w którym to przypadku zapis zwraca błąd (
EPIPE
).W twoim przykładzie oto oś czasu tego, co się dzieje:
grep
ihead
polecenia uruchomienia równoległego.grep
odczytuje dane wejściowe i rozpoczyna ich przetwarzanie.grep
produkuje pierwszy fragment danych wyjściowych.head
czyta ten pierwszy fragment i zapisuje go.grep
może zakończyć się jako pierwsza), ostateczniehead
wydrukuje żądaną liczbę linii. W tym momenciehead
wychodzi.grep
ihead
,grep
mogły zgromadzić pewne dane i jeszcze ich nie wydrukować. W momenciehead
wyjściagrep
może odczytywać dane wejściowe lub przetwarzać wewnętrznie, w którym to przypadku będzie kontynuować.grep
wypisze przetwarzane dane. W tym momencie otrzyma SIGPIPE i umrze.Prawdopodobnie
grep
przetworzy nieco więcej danych niż jest to absolutnie konieczne, ale zwykle tylko kilka kilobajtów:head
zwykle odczytuje fragmenty po kilka kilobajtów (ponieważ jest to bardziej wydajne niżread
wywołanie systemowe dla każdego bajtu - takie zachowanie nazywa się buforowaniem), więc pozostała część ostatniego fragmentu po żądanym ostatnim wierszu jest odrzucana.grep
mogło zgromadzić pewne dane, które są gotowe do przekształcenia się w fragment wyjściowy (ponowne buforowanie). Otrzyma SIGPIPE, gdy będzie próbował opróżnić bufor wyjściowy.Podsumowując, system jest precyzyjnie zaprojektowany, aby narzędzia filtrujące działały naturalnie wydajnie. Programy, które muszą kontynuować pracę po zaniku kanału wyjściowego, muszą zignorować sygnał SIGPIPE.
źródło
Sortof, potok działa w ten sposób: najpierw wykonuje pierwsze polecenie, a następnie drugie polecenie w twoim przypadku.
Oznacza to, że
A|B
otrzymamy polecenie. Wtedy nie ma pewności, czyA
lubB
zaczyna pierwszy. Mogą rozpocząć się dokładnie w tym samym czasie, jeśli jest wiele procesorów. Potok może przechowywać nieokreśloną, ale skończoną ilość danych.Jeśli B spróbuje odczytać z potoku, ale żadne dane nie są dostępne,
B
poczeka, aż dane dotrą. JeśliB
odczytuje z dysku,B
może występować ten sam problem i trzeba poczekać, aż odczyt z dysku się zakończy. Dokładniejszą analogią byłoby czytanie z klawiatury. TamB
musiałby czekać na wpisanie przez użytkownika. Ale we wszystkich tych przypadkach B rozpoczął operację „odczytu” i musi poczekać, aż zakończy. Ale jeśliB
jest to polecenie, które potrzebuje tylko częściowego wyjścia,A
to po pewnym punkcie, w którymB
osiągnięty jest poziom wejściowyA
zostanie zabity przez SIGPIPEJeśli
A
spróbujesz pisać do potoku, a potok jest pełny,A
musisz poczekać , aż wolne miejsce w potoku stanie się wolne.A
mógłby mieć ten sam problem, gdyby zapisywał na terminalu. Terminal ma kontrolę przepływu i może moderować tempo danych. W każdym razie doA
, rozpoczął operację „zapisu” i zaczeka na zakończenie operacji zapisu.A
iB
zachowują się jak koprocesy, chociaż nie wszystkie koprocesy będą komunikować się z potokiem. Żadna z nich nie ma pełnej kontroli nad drugą.źródło
head
Wyjścia), w programie pojawia się sygnał SIGPIPE i domyślnym zachowaniem jest wyjście.grep
nie ma bezpośredniej kontroli nad potokiem (tylko odbiera dane), a potok nie ma bezpośredniej kontroli nadgrep
(tylko wysyła dane) ...To
grep
, co robi lub jakikolwiek inny program, zależy całkowicie od wewnętrznej logiki tych programów. Jeśli powieszgrep
za pomocą opcji wiersza poleceń, aby zrobić wczesne wyjście po znalezieniu , zrobi to, w przeciwnym razie wypali się na samym końcu pliku, szukając wzorca ...Terminal jest również zupełnie odłączony od wewnętrznych działań
grep
ishell
działań związanych z instalowaniem potoków ... Terminal jest w zasadzie tylko polem startowym, a wyświetlacz wyjściowy ...źródło