Come capire le pipe


21

Quando ho appena usato pipe in bash, non ci ho pensato più. Ma quando leggo alcuni esempi di codice C usando system call pipe () insieme a fork (), mi chiedo come capire le pipe, comprese sia le pipe anonime che quelle con nome.

Si è spesso sentito che "tutto in Linux / Unix è un file". Mi chiedo se una pipe sia effettivamente un file in modo tale che una parte che collega scrive nel file pipe e l'altra parte legge dal file pipe? Se sì, dove viene creato il file della pipe per una pipe anonima? In / tmp, / dev, o ...?

Tuttavia, da esempi di pipe denominate, ho anche appreso che l'utilizzo delle pipe ha un vantaggio in termini di spazio e tempo rispetto all'uso esplicito dei file temporanei, probabilmente perché non sono coinvolti file nell'implementazione delle pipe. Inoltre le pipe sembrano non archiviare i dati come fanno i file. Quindi dubito che una pipe sia in realtà un file.

Risposte:


23

Per quanto riguarda la domanda sulle prestazioni, le pipe sono più efficienti dei file perché non è necessario alcun I / O su disco. Quindi cmd1 | cmd2è più efficiente di cmd1 > tmpfile; cmd2 < tmpfile(questo potrebbe non essere vero se tmpfileè supportato su un disco RAM o un altro dispositivo di memoria come named pipe; ma se si tratta di una pipe denominata, cmd1dovrebbe essere eseguito in background poiché il suo output può bloccare se la pipe è piena ). Se hai bisogno del risultato cmd1e devi ancora inviarne l'output cmd2, dovresti cmd1 | tee tmpfile | cmd2consentire cmd1e cmd2eseguire in parallelo evitando le operazioni di lettura del disco cmd2.

Le pipe con nome sono utili se molti processi leggono / scrivono nella stessa pipe. Possono anche essere utili quando un programma non è progettato per utilizzare stdin / stdout per il suo IO che necessita di usare file . Metto i file in corsivo perché le named pipe non sono esattamente file dal punto di vista della memoria poiché risiedono in memoria e hanno una dimensione del buffer fissa, anche se hanno una voce del filesystem (a scopo di riferimento). Altre cose in UNIX hanno voci del filesystem senza essere file: basti pensare a /dev/nullo ad altre voci in /devo /proc.

Poiché le pipe (denominate e senza nome) hanno una dimensione del buffer fissa, le operazioni di lettura / scrittura possono bloccarsi, causando il processo di lettura / scrittura nello stato IOWait. Inoltre, quando ricevi un EOF quando leggi da un buffer di memoria? Le regole su questo comportamento sono ben definite e possono essere trovate nell'uomo.

Una cosa che non puoi fare con le pipe (nominate e senza nome) è cercare nei dati. Dato che sono implementati usando un buffer di memoria, questo è comprensibile.

A proposito "everything in Linux/Unix is a file", non sono d'accordo. Le pipe denominate hanno voci nel filesystem, ma non sono esattamente file. Le pipe senza nome non hanno voci nel filesystem (tranne forse in /proc). Tuttavia, la maggior parte delle operazioni di I / O su UNIX viene eseguita utilizzando la funzione di lettura / scrittura che richiede un descrittore di file , incluso pipe (e socket) senza nome. Non penso che possiamo dirlo "everything in Linux/Unix is a file", ma possiamo sicuramente dirlo "most IO in Linux/Unix is done using a file descriptor".


Grazie! I due comandi sono collegati da una pipe in esecuzione in parallelo, invece che la seconda inizia a funzionare dopo che la prima è terminata?
Tim

Sì, i 2 comandi vengono eseguiti in parallelo. Se non lo fossero e il primo output fosse superiore al buffer, sarebbe bloccato. Puoi provarlo eseguendo cmd1 > fifoe cmd2 < fifoin 2 diverse shell, creando la pipe con nome mkfifo fifo.
jfg956,

Un altro test che puoi fare è uccidere cmd2mentre cmd1è ancora in esecuzione: cmd1probabilmente smetterà di riportare un messaggio di tubo rotto.
jfg956,

Grazie! cosa vuoi dire sarebbe bloccato? Se ciò accade, significa che la data nello stream dopo il blocco andrà persa?
Tim

2
I dati non vengono persi. Se il buffer della pipe è pieno, cmd1la scrittura sulla pipe restituirà solo quando cmd2avrà letto i dati dalla pipe. Allo stesso modo, cmd2la lettura di una pipe si bloccherà se il buffer è vuoto fino a quando non cmd1scrive sulla pipe.
jfg956,

4

Due dei fondamenti di base della filosofia UNIX sono

  1. Fare piccoli programmi che fanno bene una cosa.
  2. e aspettarsi che l'output di ogni programma diventi l'input per un altro programma,
    ancora sconosciuto.

    L'uso di pipe consente di sfruttare gli effetti di questi due
    fondamenti di progettazione per creare catene di comandi estremamente potenti per ottenere il risultato desiderato.

    La maggior parte dei programmi da riga di comando che operano su file può anche accettare input su standard in (input tramite tastiera) e output su standard out (stampa su
    schermo).

    Alcuni comandi sono progettati per funzionare solo all'interno di una pipe non possono operare direttamente sui file.

    per esempio trcomando

  ls -C | tr 'a-z' 'A-Z'
    cmd1 | cmd2
  • Invia STDOUT di cmd1 a STDIN di cmd2 anziché lo schermo.

  • STDERR non viene inoltrato attraverso i tubi.

    In breve, è Pipes is character (|)possibile collegare i comandi.

    Qualsiasi comando che scrive su STDOUT può essere utilizzato sul lato sinistro della pipe.

       ls - /etc | less 

    Qualsiasi comando che legge da STDIN può essere utilizzato sul lato destro di una pipe.

       echo "test print" | lpr 

    Una pipe tradizionale è "senza nome" perché esiste in forma anonima e persiste solo finché il processo è in esecuzione. Una pipe denominata è persistente nel sistema ed esiste oltre la durata del processo e deve essere eliminata quando non viene più utilizzata. I processi generalmente si collegano alla pipe denominata (di solito appare come un file) per eseguire la comunicazione tra processi (IPC).

fonte: http://en.wikipedia.org/wiki/Named_pipe


3

Per integrare le altre risposte ...

stdin e stdout sono descrittori di file e vengono letti e scritti come se fossero file. quindi puoi farlo echo hi | grep hi, e sostituirà lo stdout dell'eco con una pipe e sostituirà lo stdin di grep con l'altra estremità di questa pipe.


1

Tutto è un file.

Se prendiamo la frase troppo alla lettera, finiremmo con il significato di "abbiamo solo file e nient'altro". Questa non è l'interpretazione corretta, quindi cos'è.

Quando diciamo "Tutto è un file", non stiamo dicendo che tutto è archiviato su un disco. Stiamo dicendo che tutto sembra un file, può essere letto, può essere scritto.

In Unix, una volta aperto un file o non file, può essere trattato come un file. Tuttavia, non tutti i file supportano tutte le operazioni. Ad esempio alcuni file (che non sono file), non supportano la ricerca: devono essere letti / scritti in sequenza (questo vale per pipe e socket).

Tutto ha un nome di file (su alcuni sistemi: ad es. Debian Gnu / Linux e molti altri Gnu / Linux).

  • Tutti i file aperti ottengono un nome file. Vedere/proc/self/fd/…
  • Le prese di rete possono essere aperte con un nome file, /dev/tcp
    ad escat </dev/tcp/towel.blinkenlights.nl/23

Quest'ultima parte è valida solo su sistemi con un /procfilesystem e su sistemi (o shell) che forniscono una /dev/tcpstruttura di file.
Kusalananda
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.