Pipeline (Unix) - Pipeline (Unix)

O conductă de trei procese de program rulează pe un terminal text

În Unix- ului de calculator sisteme de operare , o conductă este un mecanism de comunicare inter-proces utilizând un mesaj de trecere. O conductă este un set de procese înlănțuite între ele prin fluxurile lor standard , astfel încât textul de ieșire al fiecărui proces ( stdout ) este trecut direct ca intrare ( stdin ) la următorul. Al doilea proces este început, deoarece primul proces este încă în curs de executare și sunt executate simultan . Conceptul de conducte a fost susținut de Douglas McIlroy la casa ancestrală a Unix , Bell Labs, în timpul dezvoltării Unix, modelându-și filozofia cutiei de instrumente . Este numit prin analogie cu o conductă fizică . O caracteristică cheie a acestor conducte este „ascunderea internelor” (Ritchie și Thompson, 1974). La rândul său, aceasta permite mai multă claritate și simplitate în sistem.

Acest articol se referă la țevi anonime , unde datele scrise de un proces sunt tamponate de sistemul de operare până când sunt citite de următorul proces, iar acest canal unidirecțional dispare când procesele sunt finalizate. Aceasta diferă de țevile numite , unde mesajele sunt transmise către sau dintr-o țeavă numită făcându-l un fișier și rămâne după finalizarea proceselor. Sintaxa standard a shell-ului pentru țevile anonime este să listeze mai multe comenzi, separate prin bare verticale („țevi” în verbele comune Unix):

command1 | command2 | command3

De exemplu, pentru a lista fișierele din directorul curent ( ls ), păstrați doar liniile de ieșire ls care conțin șirul „cheie” ( grep ) și vizualizați rezultatul într-o pagină de derulare ( mai puțin ), un utilizator tastează următoarele în linia de comandă a unui terminal:

ls -l | grep key | less

Comanda ls -leste executată ca un proces, a cărui ieșire (stdout) este conectată la intrarea (stdin) a procesului pentru grep key; și la fel pentru procesul pentru less. Fiecare proces preia intrări din procesul anterior și produce ieșiri pentru următorul proces prin fluxuri standard . Fiecare |spune shell-ului să conecteze ieșirea standard a comenzii din stânga la intrarea standard a comenzii din dreapta printr-un mecanism de comunicare inter-proces numit o conductă (anonimă) , implementat în sistemul de operare. Țevile sunt unidirecționale; datele curg prin conductă de la stânga la dreapta.

Exemplu

Mai jos este un exemplu de conductă care implementează un fel de verificator ortografic pentru resursa web indicată de o adresă URL . Urmează o explicație a ceea ce face.

curl "https://en.wikipedia.org/wiki/Pipeline_(Unix)" |
sed 's/[^a-zA-Z ]/ /g' |
tr 'A-Z ' 'a-z\n' |
grep '[a-z]' |
sort -u |
comm -23 - <(sort /usr/share/dict/words) |
less
  1. curlobține conținutul HTML al unei pagini web (ar putea fi utilizat wgetpe unele sisteme).
  2. sedînlocuiește toate caracterele (din conținutul paginii web) care nu sunt spații sau litere, cu spații. ( Newlines sunt păstrate.)
  3. tr schimbă toate literele majuscule în minuscule și convertește spațiile din liniile de text în linii noi (fiecare „cuvânt” este acum pe o linie separată).
  4. grepinclude numai linii care conțin cel puțin un caracter alfabetic minuscul (eliminarea oricăror linii goale).
  5. sortsortează lista „cuvintelor” în ordine alfabetică, iar -ucomutatorul elimină duplicatele.
  6. commgăsește linii în comun între două fișiere, -23elimină liniile unice pentru al doilea fișier și cele comune pentru ambele, lăsând doar cele care se găsesc numai în primul fișier numit. În -locul unui nume de fișier, commse folosește intrarea sa standard (de la conductă în acest caz). sort /usr/share/dict/wordssortează conținutul wordsfișierului în ordine alfabetică, așa cum commse așteaptă, și <( ... )scoate rezultatele într-un fișier temporar (prin substituirea procesului ), care commcitește. Rezultatul este o listă de cuvinte (linii) care nu se găsesc în / usr / share / dict / words.
  7. less permite utilizatorului să parcurgă rezultatele.

Conducte în interfețele liniei de comandă

Toate shell-urile Unix utilizate pe scară largă au o construcție specială de sintaxă pentru crearea conductelor. In toate folosinta scrie comenzile în ordine, separate prin ASCII bara verticală caracter |(care, din acest motiv, este adesea numit „caracter pipe“). Shell-ul pornește procesele și aranjează conexiunile necesare între fluxurile lor standard (inclusiv o cantitate de stocare tampon ).

Flux de erori

În mod implicit, fluxurile de erori standard („ stderr ”) ale proceselor dintr-o conductă nu sunt transmise prin conductă; în schimb, sunt îmbinate și direcționate către consolă . Cu toate acestea, multe shell-uri au o sintaxă suplimentară pentru schimbarea acestui comportament. În shell-ul csh , de exemplu, utilizarea |&în loc de |înseamnă că fluxul de erori standard ar trebui, de asemenea, să fie îmbinat cu ieșirea standard și să fie alimentat la următorul proces. Bourne Shell poate fuziona , de asemenea , eroare standard cu |&deoarece bash 4.0 sau folosind 2>&1, precum și redirecționeze către un alt fișier.

Pipemill

În cele mai frecvent utilizate conducte simple, shell-ul conectează o serie de subprocese prin conducte și execută comenzi externe în cadrul fiecărui subproces. Astfel, shell-ul în sine nu face nicio procesare directă a datelor care curg prin conductă.

Cu toate acestea, este posibil ca shell-ul să efectueze procesarea direct, utilizând așa-numita moară sau pipemill (deoarece o whilecomandă este utilizată pentru a „mori” peste rezultatele din comanda inițială). Această construcție arată, în general, ca:

command | while read -r var1 var2 ...; do
    # process each line, using variables as parsed into var1, var2, etc
    # (note that this may be a subshell: var1, var2 etc will not be available
    # after the while loop terminates; some shells, such as zsh and newer
    # versions of Korn shell, process the commands to the left of the pipe
    # operator in a subshell)
    done

O astfel de pipemill nu poate funcționa așa cum s-a intenționat dacă corpul buclei include comenzi, cum ar fi catși ssh, care se citesc din stdin: pe prima iterație a buclei, un astfel de program (să-l numim drenaj ) va citi ieșirea rămasă din command, și bucla se va termina apoi (cu rezultate în funcție de specificul scurgerii). Există câteva modalități posibile de a evita acest comportament. În primul rând, unele scurgeri acceptă o opțiune pentru a dezactiva citirea din stdin(de exemplu ssh -n). Alternativ, dacă canalul de scurgere nu are nevoie să citească nicio intrare stdinpentru a face ceva util, poate fi dat < /dev/nullca intrare.

Deoarece toate componentele unei țevi sunt rulate în paralel, un shell în mod obișnuit forchează un subproces (un subshell) pentru a gestiona conținutul acestuia, făcând imposibilă propagarea modificărilor variabile în mediul shell exterior. Pentru a remedia această problemă, "pipemill" poate fi în schimb alimentat dintr-un document de aici care conține o substituție de comandă , care așteaptă ca conducta să se finalizeze înainte de a freza conținutul. Alternativ, o țeavă numită sau o înlocuire de proces poate fi utilizată pentru execuția paralelă. GNU bash are, de asemenea, o lastpipeopțiune pentru a dezactiva bifurcarea pentru ultima componentă a conductei.

Crearea conductelor programat

Conductele pot fi create sub controlul programului. pipe() Apelul de sistem Unix solicită sistemului de operare să construiască un nou obiect anonim . Acest lucru are ca rezultat doi descriptori de fișiere noi, deschise în acest proces: capătul numai în citire al țevii și capătul numai în scriere. Capetele conductelor par a fi descriptori de fișiere anonimi normali , cu excepția faptului că nu au capacitatea de a căuta.

Pentru a evita blocajul și a exploata paralelismul, procesul Unix cu una sau mai multe conducte noi va apela, în general, fork()pentru a crea noi procese. Fiecare proces va închide apoi capătul (conductele) conductei pe care nu le va folosi înainte de a produce sau consuma date. Alternativ, un proces poate crea fire noi și poate utiliza conducta pentru a comunica între ele.

Țevile denumite pot fi create de asemenea folosindmkfifo()saumknod()și apoi prezentate ca fișier de intrare sau de ieșire la programe pe măsură ce sunt invocate. Acestea permit crearea de țevi cu mai multe căi și sunt deosebit de eficiente atunci când sunt combinate cu redirecționarea erorilor standard sau cutee.

Implementare

În majoritatea sistemelor de tip Unix, toate procesele unei conducte sunt pornite în același timp, cu fluxurile lor conectate corespunzător și gestionate de programator împreună cu toate celelalte procese care rulează pe mașină. Un aspect important al acestui fapt, diferențierea conductelor Unix de alte implementări de conducte, este conceptul de tamponare : de exemplu, un program de trimitere poate produce 5000 de octeți pe secundă , iar un program de recepție poate accepta doar 100 de octeți pe secundă, dar nu datele sunt pierdute. În schimb, ieșirea programului de trimitere este păstrată în buffer. Când programul de recepție este gata să citească date, atunci următorul program din conductă citește din buffer. În Linux, dimensiunea bufferului este de 65.536 octeți (64 KB). Un filtru open source terță parte numit bfr este disponibil pentru a oferi tampoane mai mari, dacă este necesar.

Conducte de rețea

Instrumente precum netcat și socat pot conecta conducte la prize TCP / IP .

Istorie

Conceptul de conducte a fost inventat de Douglas McIlroy și descris pentru prima dată în paginile manuale ale versiunii 3 Unix . McIlroy a observat că o mare parte din shell-urile de comandă au trecut fișierul de ieșire dintr-un program ca intrare în altul.

Ideile sale au fost puse în aplicare în 1973 când („într-o noapte febrilă”, a scris McIlroy) Ken Thompson a adăugat pipe()apelul de sistem și conductele la shell și mai multe utilități în versiunea 3 Unix. „A doua zi”, a continuat McIlroy, „a văzut o orgie de neuitat a celor care se învârteau pe măsură ce toată lumea se alătura entuziasmului instalațiilor sanitare”. McIlroy îl recunoaște, de asemenea, pe Thompson cu |notația, care a simplificat foarte mult descrierea sintaxei conductelor în versiunea 4 .

Deși dezvoltate independent, conductele Unix sunt legate de și au fost precedate de „fișierele de comunicare” dezvoltate de Ken Lochner în anii 1960 pentru Dartmouth Time Sharing System .

În procesele secvențiale de comunicare (CSP) ale lui Tony Hoare , conductele lui McIlroy sunt dezvoltate în continuare.

Robotul din pictograma pentru Apple 's Automator , care folosește, de asemenea, un concept de conductă pentru a înlănțui comenzi repetitive, ține o conductă în omagiu conceptului original Unix.

Alte sisteme de operare

Această caracteristică a Unix a fost împrumutată de alte sisteme de operare, cum ar fi MS-DOS și pachetul CMS Pipelines pe VM / CMS și MVS , și în cele din urmă a ajuns să fie desemnat modelul de proiectare a conductelor și filtrelor de inginerie software .

Vezi si

Referințe

linkuri externe