Jaka jest dokładna pomysłowość uniksowej rury

52

Słyszałem historię, jak Douglas Mcllroy wpadł na pomysł i jak Ken Thompson wdrożył go w ciągu jednej nocy.

O ile rozumiem, potok jest wywołaniem systemowym, które dzieli część pamięci między dwoma procesami, w których jeden proces pisze, a drugi czyta.

Jako ktoś, kto nie jest zaznajomiony z elementami wewnętrznymi i koncepcjami systemu operacyjnego, zastanawiałem się, czym dokładnie jest „geniusz” w tej historii? Czy to pomysł dwóch procesów dzielących pamięć? A może to wdrożenie? Lub obydwa?

PS: Zdaję sobie sprawę z użyteczności potoku lub jak go używać w powłoce. Pytanie dotyczy koncepcji i wdrożenia|

słaby
źródło
4
Wydaje mi się, że w tamtych czasach zdecydowanie naciskało się na wdrożenie mechanizmu tworzenia aplikacji. Aby to zrobić, musisz mieć dobrze sformułowaną koncepcję oddzielenia interfejsu od implementacji i uświadomić sobie użyteczność kompozycji funkcjonalnej w programowaniu.
Chan-Ho Suh,
4
Mało tego, już uruchomione aplikacje miały uchwyt wejścia standardowego i uchwyt wyjścia standardowego, a interfejsy API systemu operacyjnego typu Unix miały funkcje odczytu / zapisu do tych uchwytów. Sprytne użycie kilku ortogonalnych i wysoce wydajnych koncepcji (uchwytów, danych wyjściowych i wejściowych z nich) prowadzi nie tylko do potoków, ale także do gniazd, interakcji znak-urządzenie i dziesiątków innych rzeczy. Teraz, gdy mamy już uchwyty plików (dla tty, który zapewnia wprowadzanie za pomocą klawiatury i tekst), stwórzmy aplikacje tak, aby jedna aplikacja stała się tty drugiej.
Warren P,
6
@WarrenP Faktycznie Unix drogę o standardowej wejście i standardowego wyjścia ze względu na pipe()syscall i |operatora powłoki (Ref Mcilroy ). Lub, jak powiedziałby Voltaire, „ gdyby [stdio] nie istniało, konieczne byłoby wymyślenie [go]. ” :-)
Ross Patterson
Nie było czegoś takiego, jak uchwyt do segregatora oraz uchwyt do wkładania i wyjmowania, dopóki PO rurach nie?
Warren P,
4
@WarrenP: Wygląda na to, że Patterson mówi: najpierw były uchwyty do plików. Potem ci ludzie wpadli na pomysł, że każdy program domyślnie ma uchwyt wejściowy i wyjściowy, co następnie pozwala programom na trywialne połączenie. Stały się one znane jako „standardowe” wejście / wyjście.
Kaczka Mooing

Odpowiedzi:

109

O ile rozumiem, potok jest wywołaniem systemowym, które dzieli część pamięci między dwoma procesami, w których jeden proces pisze, a drugi czyta.

W rzeczywistości nie dotyczy to pamięci współdzielonej. Czytnik i pisarz NIE współużytkują żadnej części swojej przestrzeni adresowej i nie używają żadnej wyraźnej synchronizacji.

Procesy odczytywania i zapisywania są wywoływane readi writewywoływane przez system dokładnie tak , jak gdyby odczytywały / zapisywały do ​​pliku. TO jest geniusz ... innowacja: pojęcie, że (prosta) komunikacja międzyprocesowa i plikowe I / O mogą być obsługiwane w ten sam sposób ... z perspektywy programisty aplikacji i użytkownika.

Po skonfigurowaniu potoku system operacyjny (nie kod aplikacji lub biblioteki w przestrzeni użytkownika) zajmuje się buforowaniem i koordynacją. Transparentnie


Natomiast przed wynalezieniem koncepcji potoku, jeśli trzeba było wykonać przetwarzanie „potokowe”, zwykle jedna aplikacja zapisuje dane wyjściowe do pliku, a następnie po zakończeniu uruchamia drugą aplikację do odczytu z pliku plik.

Alternatywnie, jeśli chcesz prawdziwego potoku, możesz zakodować obie aplikacje, aby skonfigurować (rzeczywisty) segment pamięci dzielonej i użyć semaforów (lub czegoś innego) do koordynowania odczytu / zapisu. Skomplikowane ... i w konsekwencji rzadko wykonywane.

Stephen C.
źródło
34
„TO jest geniusz… innowacja: koncepcja, że ​​komunikacja międzyprocesowa i pliki I / O mogą być obsługiwane w ten sam sposób” - dokładnie to. Pozwala na komunikację międzyprocesową między programami, które nigdy nie zostały tak zaprojektowane, a nawet (nie muszą) wiedzieć, co się dzieje.
Guntram Blohm obsługuje Monikę
6
Warto również zauważyć, że powód użycia pliku I / O dla IPC był głównie użyteczny, ponieważ Unix został zaprojektowany do przetwarzania tekstu - przesyłania strumieniowego danych tekstowych z programu do programu, umożliwiając stosunkowo bezbolesną kompozycję, co z kolei oznaczało, że cały system można zbudować z stosunkowo proste, małe programy, które przesyłały strumieniowo dane między sobą w (prawdopodobnie) długim łańcuchu prostych operacji. Zasadniczo oznaczało to, że masz stosunkowo elastyczny język do obsługi przetwarzania tekstu.
Luaan,
1
I tak „pomysłowość uniksowego potoku” to „pomysłowość uniksowego”: wszystkie operacje we / wy (w tym komunikacja międzyprocesowa, standardowe pliki i reszta obiektów systemu plików) są traktowane jak pliki.
Mark Hurd,
Kolejnym genialnym
pomysłem
14

Moim zdaniem genialność pomysłu „fajki” polega na prostocie użytkowania.

Nie musisz wykonywać żadnych wywołań systemowych, alokować pamięci, nic skomplikowanego. W powłoce, należy użyć pojedynczego znaku: |. Daje to niezwykłą moc w kombinacji prostych (lub złożonych) narzędzi do danego zadania.

Wykonuj typowe codzienne zadania, takie jak porządne sortowanie tekstu. Możesz mieć polecenie, które wyświetla całą grupę nazw. (W moim przykładzie użyję pliku zawierającego kilka nazw, dzięki uprzejmości listofrandomnames.com.) Za pomocą potoków możesz wykonać następujące czynności:

$ cat names.txt
Sally Weikel
Dana Penaflor
Christine Hook
Shaneka Flythe
Almeda Crook
Freddie Lindley
Hester Kersh
Wanda Ruse
Megan Mauzy
Samuel Mancha
Paris Phipps
Annika Accardo
Elena Nabors
Caroline Foti
Jude Nesby
Chase Gordy
Carmela Driggers
Marlin Ostendorf
Harrison Dauber
$ cat names.txt | awk '{print $2 ", " $1}' | sort | uniq | column -c 100
Accardo, Annika     Hook, Christine     Ostendorf, Marlin
Crook, Almeda       Kersh, Hester       Penaflor, Dana
Dauber, Harrison    Lindley, Freddie    Phipps, Paris
Driggers, Carmela   Mancha, Samuel      Ruse, Wanda
Flythe, Shaneka     Mauzy, Megan        Weikel, Sally
Foti, Caroline      Nabors, Elena
Gordy, Chase        Nesby, Jude

To tylko przykład; są tysiące. Aby zapoznać się z kilkoma innymi konkretnymi zadaniami, które są znacznie łatwiejsze dzięki zastosowaniu potoków, zobacz sekcję „The Unix Philosophy” na tej stronie .


Aby podkreślić tę odpowiedź, zobacz slajdy od 4 do 9 prezentacji „Dlaczego Zsh jest chłodniejszy od twojej powłoki”.


Wiem, że powyższe polecenie zawiera kod UUOC . Daję temu spokój, ponieważ jest symbolem zastępczym dowolnego polecenia generującego tekst.

Dzika karta
źródło
3
Malutka drobna notatka : sort -umoże wykonać zadanie sort | uniqszybciej.
Iwillnotexist Idonotexist
cat names.txt | awk '{print $2 ", " $1}' | sort | uniq | column -c 100Możesz się do tego przyzwyczaić, ale wcale nie nazwałbym tego prostym. Zwłaszcza awkczęść.
Federico Poloni,
Te rury są proste. Powiedziałem: „... niezwykła moc w połączeniu prostych (lub złożonych) narzędzi do danego zadania”.
Wildcard
5

Próbowałem więc trochę zbadać to, szukając instrukcji PDP-10 / TOPS-10, aby dowiedzieć się, jaki jest stan techniki przed wprowadzeniem rur. Znalazłem to , ale TOPS-10 jest niezwykle trudny do znalezienia w Google. Istnieje kilka dobrych referencji na temat wynalezienia potoku: wywiad z McIlroy , historia i wpływ UNIX .

Musisz umieścić to w kontekście historycznym. Istniało niewiele nowoczesnych narzędzi i udogodnień, które uważamy za coś oczywistego.

„Na początku Thompson nawet nie programował na samym PDP, ale zamiast tego używał zestawu makr dla asemblera GEMAP na maszynie GE-635.” (29) Taśma papierowa została wygenerowana na GE 635, a następnie przetestowana na PDP-7 do momentu, gdy według Ritchie „pierwotne jądro Uniksa, edytor, asembler, prosta powłoka (interpreter poleceń) i kilka narzędzi (takich jak polecenia Unix rm, cat, cp) zostały ukończone. W tym momencie punkt, system operacyjny był samonośny, programy mogły być pisane i testowane bez uciekania się do taśmy papierowej, a rozwój samego PDP-7 był kontynuowany. ”

PDP-7 wygląda tak . Zwróć uwagę na brak interaktywnego wyświetlacza lub dysku twardego. „System plików” byłby przechowywany na taśmie magnetycznej. Pamięć programów i danych zawierała do 64 KB.

W tym środowisku programiści zwykle zwracali się bezpośrednio do sprzętu, na przykład wydając polecenia, aby podkręcić taśmę i przetwarzać znaki jeden po drugim odczytywane bezpośrednio z interfejsu taśmy. UNIX zapewnił abstrakcje na ten temat, aby zamiast „czytać z teletype” i „czytać z taśmy” jako oddzielne interfejsy, zostały one połączone w jeden, z kluczowym dodaniem potoku „odczyt z wyjścia innego programu bez przechowywania tymczasowej kopii na dysku” lub taśma ”.

Oto McIlroy na temat wynalazku grep. Myślę, że dobrze to podsumowuje ilość pracy wymaganej w środowisku starszym niż UNIX.

„Grep został dla mnie wymyślony. Tworzyłem program do odczytywania tekstu na głos za pomocą syntezatora mowy. Gdy wymyśliłem reguły fonetyczne, sprawdzałem w słowniku Webstera słowa, na których mogą się nie powieść. Na przykład, jak sobie radzisz z digrafem” ui ”, które wymawia się na wiele różnych sposobów:„ owoc ”,„ podstęp ”,„ winny ”,„ udręka ”,„ intuicja ”,„ beguine ”? Rozbiłbym słownik na części, które mieszczą się w ograniczonym buforze i użyciu Eda globalne polecenie, aby wybrać listę. Zmniejszę tę listę, powtarzając skanowanie za pomocą ed, aby zobaczyć, jak działa każda proponowana reguła. ”

„Proces był żmudny i strasznie marnotrawny, ponieważ słownik musiał zostać podzielony (nie było stać na pozostawienie podzielonej kopii w linii). Następnie ed skopiował każdą część do / tmp, przeskanował ją dwukrotnie, aby wykonać polecenie g, i w końcu go wyrzuciłem, co również wymaga czasu. ”

„Pewnego popołudnia zapytałem Kena Thompsona, czy mógłby wyciągnąć z edytora funkcję rozpoznawania wyrażeń regularnych i zrobić jednoprzebiegowy program. Powiedział tak. Następnego ranka znalazłem notatkę w poczcie z ogłoszeniem programu o nazwie grep. Działało to jak urok. Zapytany, co oznacza to śmieszne imię, Ken powiedział, że to oczywiste. Oznaczało to polecenie edytora, które symulował, g / re / p (globalny wydruk wyrażeń regularnych).

Porównaj pierwszą część tego cat names.txt | awk '{print $2 ", " $1}' | sort | uniq | column -c 100przykładu. Jeśli twoimi opcjami jest „budowanie linii poleceń” kontra „napisz program specjalnie do tego celu, ręcznie, w asemblerze”, to warto zbudować linię poleceń. Nawet jeśli zajmie to kilka godzin przeczytanie instrukcji (papierowych). Następnie możesz zapisać go do wykorzystania w przyszłości.

pjc50
źródło
1

Geniusz Pipe polega na tym, że łączy w sobie trzy ważne pomysły.

Po pierwsze, rury są praktyczną implementacją „wspólnych procedur”, terminu wymyślonego przez Conwaya w 1958 roku, który był obiecujący, ale nie znalazł praktycznego zastosowania przed rurami.

Po drugie, implementując rury w języku powłoki, Thompson i in. Wymyślili pierwszy prawdziwy „język kleju”.

Te dwa punkty umożliwiają wydajne opracowanie komponentów oprogramowania wielokrotnego użytku w zoptymalizowanym języku niskiego poziomu, a następnie sklejenie ze sobą w celu uzyskania znacznie większej, bardziej złożonej funkcjonalności. Nazwali to „Programowaniem na dużą skalę”.

Po trzecie, implementacja potoków przy użyciu tych samych wywołań systemowych, które były używane do dostępu do plików, umożliwiła pisanie programów z uniwersalnymi interfejsami. Pozwoliło to na prawdziwie uniwersalne rozwiązania problemów z oprogramowaniem, z których można korzystać interaktywnie, wykorzystując dane z plików oraz jako część większych systemów oprogramowania, wszystko bez jednej zmiany w komponentach oprogramowania. Bez kompilacji, bez konfiguracji, tylko kilka prostych poleceń powłoki.

Jeśli chcesz przejść przez krzywą uczenia się, oprogramowanie UNIX jest dziś równie przydatne, jak 40 lat temu. Nieustannie odkrywamy rzeczy, które już znali i opracowaliśmy rozwiązania. Kluczowym przełomem była prosta rura. Jedyną prawdziwą innowacją po tym było stworzenie Internetu w latach 80-tych. Dramatycznie UNIX spartaczył tę implementację, tworząc osobny interfejs API. Nadal ponosimy konsekwencje ... Och, tak, było coś z wyświetlaczy wideo i myszy, które stały się popularne pod koniec lat 80-tych. Ale to dotyczy WIMP.

EvertW
źródło