Domanda

Qualcuno sa come bash gestisce l'invio di dati tramite pipe?

cat file.txt | tail -20

Questo comando stampa tutto il contenuto di file.txt in un buffer, che viene poi letto da tail?Oppure questo comando, ad esempio, stampa il contenuto di file.txt riga per riga, quindi fa una pausa su ogni riga affinché tail venga elaborato, quindi richiede più dati?

Il motivo per cui lo chiedo è che sto scrivendo un programma su un dispositivo incorporato che sostanzialmente esegue una sequenza di operazioni su una porzione di dati, in cui l'output di un'operazione viene inviato come input dell'operazione successiva.Vorrei sapere come Linux (bash) gestisce questo problema, quindi per favore dammi una risposta generale, non specificamente cosa succede quando eseguo "cat file.txt | tail -20".

Grazie in anticipo per le vostre risposte!

MODIFICARE:Shog9 ha segnalato un articolo di Wikipedia pertinente, questo non mi ha portato direttamente all'articolo ma mi ha aiutato a trovare questo: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation che conteneva le informazioni che stavo cercando.


Mi spiace di non essere stato chiaro.Ovviamente stai usando una pipe e ovviamente stai usando stdin e stdout delle rispettive parti del comando.Avevo pensato che fosse troppo ovvio per dirlo.

Quello che sto chiedendo è come questo viene gestito/implementato.Poiché entrambi i programmi non possono essere eseguiti contemporaneamente, come vengono inviati i dati da stdin a stdout?Cosa succede se il primo programma genera dati molto più velocemente del secondo programma?Il sistema esegue semplicemente il primo comando fino a quando non viene terminato o il buffer stdout è pieno, quindi passa al programma successivo e così via in ciclo fino a quando non rimangono più dati da elaborare o esiste un meccanismo più complicato ?

È stato utile?

Soluzione

Ho deciso di scrivere una spiegazione un po' più dettagliata.

La "magia" qui sta nel sistema operativo.Entrambi i programmi si avviano all'incirca nello stesso momento e vengono eseguiti contemporaneamente (il sistema operativo assegna loro porzioni di tempo sul processore per l'esecuzione) come ogni altro processo in esecuzione simultaneamente sul computer (inclusa l'applicazione terminale e il kernel) .Pertanto, prima che i dati vengano trasmessi, i processi eseguono tutta l'inizializzazione necessaria.Nel tuo esempio, tail sta analizzando l'argomento "-20" e cat sta analizzando l'argomento "file.txt" e aprendo il file.Ad un certo punto la coda arriverà al punto in cui avrà bisogno di input e dirà al sistema operativo che è in attesa di input.Ad un certo punto (prima o dopo, non importa) cat inizierà a passare i dati al sistema operativo utilizzando stdout.Questo va in un buffer nel sistema operativo.La prossima volta che tail ottiene una porzione di tempo sul processore dopo che alcuni dati sono stati inseriti nel buffer da cat, recupererà una parte di quei dati (o tutti) che lasciano il buffer sul sistema operativo.Quando il buffer è vuoto, a un certo punto tail dovrà attendere che cat generi più dati.Se cat emette dati molto più velocemente di quanto tail li gestisca, il buffer si espanderà.cat alla fine avrà finito di emettere i dati, ma tail sarà ancora in fase di elaborazione, quindi cat si chiuderà e tail elaborerà tutti i dati rimanenti nel buffer.Il sistema operativo segnalerà la coda quando non ci saranno più dati in arrivo con un EOF.Tail elaborerà i dati rimanenti.In questo caso, tail probabilmente sta semplicemente ricevendo tutti i dati in un buffer circolare di 20 righe, e quando viene segnalato dal sistema operativo che non ci sono più dati in arrivo, scarica le ultime venti righe sul proprio stdout, che viene semplicemente visualizzato nel terminale.Poiché tail è un programma molto più semplice di cat, probabilmente trascorrerà la maggior parte del tempo aspettando che cat inserisca i dati nel buffer.

Su un sistema con più processori, i due programmi non solo condivideranno intervalli di tempo alternati sullo stesso core del processore, ma probabilmente verranno eseguiti contemporaneamente su core separati.

Per entrare un po' più nel dettaglio, se apri una sorta di monitor di processo (specifico del sistema operativo) come "top" in Linux vedrai un intero elenco di processi in esecuzione, la maggior parte dei quali utilizza effettivamente lo 0% del processore.La maggior parte delle applicazioni, a meno che non stiano elaborando dati, trascorrono la maggior parte del tempo senza fare nulla.Questo è positivo perché consente ad altri processi di avere accesso illimitato al processore in base alle loro esigenze.Ciò si ottiene fondamentalmente in tre modi.Un processo potrebbe arrivare a un'istruzione in stile sleep(n) in cui sostanzialmente dice al kernel di attendere n millisecondi prima di dargli un'altra porzione di tempo con cui lavorare.Più comunemente un programma deve attendere qualcosa da un altro programma, come "coda" in attesa che più dati entrino nel buffer.In questo caso il sistema operativo riattiverà il processo quando saranno disponibili più dati.Infine, il kernel può anticipare un processo nel mezzo dell'esecuzione, assegnando alcune porzioni di tempo del processore ad altri processi.'cat' e 'tail' sono programmi semplici.In questo esempio, tail trascorre la maggior parte del tempo aspettando più dati nel buffer, mentre cat trascorre la maggior parte del tempo aspettando che il sistema operativo recuperi i dati dal disco rigido.Il collo di bottiglia è la velocità (o lentezza) del supporto fisico su cui è archiviato il file.Il ritardo percettibile che potresti rilevare quando esegui questo comando per la prima volta è il tempo impiegato dalle testine di lettura sull'unità disco per cercare la posizione sul disco rigido in cui si trova "file.txt".Se esegui il comando una seconda volta, il sistema operativo avrà probabilmente il contenuto di file.txt memorizzato nella cache in memoria e probabilmente non vedrai alcun ritardo percettibile (a meno che file.txt non sia molto grande o il file non sia più memorizzato nella cache .)

La maggior parte delle operazioni che esegui sul tuo computer sono legate all'IO, vale a dire che di solito stai aspettando che i dati provengano dal tuo disco rigido o da un dispositivo di rete, ecc.

Altri suggerimenti

Shog9 ha già fatto riferimento all'articolo di Wikipedia, ma il file sezione implementazione ha i dettagli che desideri.L'implementazione di base è un buffer limitato.

cat stamperà semplicemente i dati sullo standard out, che verrà reindirizzato allo standard in tail.Questo può essere visto nella pagina man di bash.

In altre parole, non vi è alcuna pausa in corso, tail sta semplicemente leggendo dallo standard in ingresso e cat sta semplicemente scrivendo dallo standard in uscita.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top