Pergunta

Alguém sabe como o bash lida com o envio de dados através de pipes?

cat file.txt | tail -20

Este comando imprime todo o conteúdo do arquivo.txt em um buffer, que é então lido por cauda?Ou esse comando, digamos, imprime o conteúdo do arquivo.txt linha por linha e, em seguida, pausa em cada linha para processar o final e, em seguida, solicita mais dados?

A razão pela qual pergunto é que estou escrevendo um programa em um dispositivo incorporado que basicamente executa uma sequência de operações em algum pedaço de dados, onde a saída de uma operação é enviada como entrada da próxima operação.Eu gostaria de saber como o Linux (bash) lida com isso, então, por favor, me dê uma resposta geral, não especificamente o que acontece quando executo "cat file.txt | tail -20".

Agradecemos antecipadamente por suas respostas!

EDITAR:Shog9 apontou um artigo relevante da Wikipedia, isso não me levou diretamente ao artigo, mas me ajudou a encontrar isto: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation que continha as informações que eu procurava.


Sinto muito por não ter sido claro.É claro que você está usando um pipe e, claro, stdin e stdout das respectivas partes do comando.Eu presumi que isso era óbvio demais para afirmar.

O que estou perguntando é como isso é tratado/implementado.Como os dois programas não podem ser executados ao mesmo tempo, como os dados são enviados de stdin para stdout?O que acontece se o primeiro programa gerar dados significativamente mais rápido que o segundo programa?O sistema apenas executa o primeiro comando até que seja finalizado ou o buffer stdout esteja cheio e, em seguida, passe para o próximo programa e assim por diante em um loop até que não haja mais dados para serem processados ​​ou haja um mecanismo mais complicado ?

Foi útil?

Solução

Decidi escrever uma explicação um pouco mais detalhada.

A “mágica” aqui está no sistema operacional.Ambos os programas iniciam aproximadamente ao mesmo tempo e são executados ao mesmo tempo (o sistema operacional atribui intervalos de tempo no processador para serem executados) como qualquer outro processo em execução simultânea em seu computador (incluindo o aplicativo de terminal e o kernel) .Portanto, antes de qualquer dado ser transmitido, os processos fazem toda a inicialização necessária.No seu exemplo, tail está analisando o argumento '-20' e cat está analisando o argumento 'file.txt' e abrindo o arquivo.Em algum ponto, tail chegará ao ponto em que precisa de entrada e informará ao sistema operacional que está aguardando entrada.Em algum outro momento (antes ou depois, não importa) cat começará a passar dados para o sistema operacional usando stdout.Isso vai para um buffer no sistema operacional.Na próxima vez que tail obtiver um intervalo de tempo no processador depois que alguns dados forem colocados no buffer por cat, ele recuperará uma quantidade desses dados (ou todos eles) que deixam o buffer no sistema operacional.Quando o buffer está vazio, em algum momento tail terá que esperar que cat produza mais dados.Se cat estiver gerando dados muito mais rápido do que tail está manipulando-os, o buffer será expandido.cat eventualmente terminará a saída de dados, mas tail ainda estará processando, então cat fechará e tail processará todos os dados restantes no buffer.O sistema operacional sinalizará quando não houver mais dados recebidos com um EOF.Tail processará os dados restantes.Nesse caso, tail provavelmente está apenas recebendo todos os dados em um buffer circular de 20 linhas e, quando é sinalizado pelo sistema operacional que não há mais dados recebidos, ele despeja as últimas vinte linhas em seu próprio stdout, que apenas é exibido no terminal.Como tail é um programa muito mais simples que cat, ele provavelmente passará a maior parte do tempo esperando que cat coloque os dados no buffer.

Em um sistema com múltiplos processadores, os dois programas não apenas compartilharão intervalos de tempo alternados no mesmo núcleo do processador, mas provavelmente serão executados ao mesmo tempo em núcleos separados.

Para entrar em mais detalhes, se você abrir algum tipo de monitor de processo (específico do sistema operacional) como 'top' no Linux, você verá uma lista completa de processos em execução, a maioria dos quais está efetivamente usando 0% do processador.A maioria dos aplicativos, a menos que estejam processando dados, passa a maior parte do tempo sem fazer nada.Isso é bom porque permite que outros processos tenham acesso irrestrito ao processador de acordo com suas necessidades.Isto é realizado basicamente de três maneiras.Um processo pode chegar a uma instrução no estilo sleep(n), onde basicamente diz ao kernel para esperar n milissegundos antes de fornecer outro intervalo de tempo para trabalhar.Mais comumente, um programa precisa esperar por algo de outro programa, como 'tail', aguardando que mais dados entrem no buffer.Neste caso, o sistema operacional ativará o processo quando mais dados estiverem disponíveis.Por último, o kernel pode antecipar um processo no meio da execução, concedendo alguns intervalos de tempo do processador para outros processos.'cat' e 'tail' são programas simples.Neste exemplo, tail passa a maior parte do tempo esperando por mais dados no buffer, e cat passa a maior parte do tempo esperando que o sistema operacional recupere dados do disco rígido.O gargalo é a velocidade (ou lentidão) do meio físico em que o arquivo está armazenado.Esse atraso perceptível que você pode detectar ao executar este comando pela primeira vez é o tempo que leva para os cabeçotes de leitura na unidade de disco procurarem a posição no disco rígido onde está 'file.txt'.Se você executar o comando uma segunda vez, o sistema operacional provavelmente terá o conteúdo do arquivo.txt armazenado em cache na memória e você provavelmente não verá nenhum atraso perceptível (a menos que o arquivo.txt seja muito grande ou o arquivo não esteja mais armazenado em cache .)

A maioria das operações que você realiza em seu computador são vinculadas a IO, o que significa que você geralmente espera que os dados venham de seu disco rígido ou de um dispositivo de rede, etc.

Outras dicas

Shog9 já fez referência ao artigo da Wikipedia, mas o seção de implementação tem os detalhes que você deseja.A implementação básica é um buffer limitado.

cat apenas imprimirá os dados para a saída padrão, que será redirecionada para a entrada padrão da cauda.Isso pode ser visto na página de manual do bash.

Em outras palavras, não há pausa, tail está apenas lendo a entrada padrão e cat está apenas escrevendo na saída padrão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top