Os utilitários do Linux são inteligentes ao executar comandos canalizados?

23

Eu estava apenas executando alguns comandos em um terminal e comecei a pensar, o Unix / Linux toma atalhos ao executar comandos canalizados?

Por exemplo, digamos que eu tenha um arquivo com um milhão de linhas, sendo que as 10 primeiras contêm hello world . Se você executar o comando grep "hello world" file | head , o primeiro comando irá parar assim que ele encontrar 10 linhas, ou continuará a procurar o arquivo inteiro primeiro?

    
por DisgruntledGoat 25.01.2012 / 14:12

4 respostas

30

Classificar de. O shell não faz ideia do que os comandos que você está executando farão, apenas conecta a saída de um à entrada do outro.

Se grep encontrar mais de 10 linhas que digam "hello world", então head terá todas as 10 linhas desejadas e fechará o pipe. Isso fará com que grep seja eliminado com um SIGPIPE, por isso não é necessário continuar digitalizando um arquivo muito grande.

    
por 25.01.2012 / 16:31
15

Quando um programa tenta gravar em um pipe e não há leitura de processo desse pipe, o programa gravador recebe um SIGPIPE sinal. A ação padrão quando um programa recebe SIGPIPE é finalizar o programa. Um programa pode optar por ignorar o sinal SIGPIPE, em cujo caso a escrita retorna um erro ( EPIPE ).

No seu exemplo, aqui está uma linha do tempo do que acontece:

  • Os comandos grep e head são iniciados em paralelo.
  • grep lê alguma entrada, começa a processá-la.
  • Em algum momento, grep produz um primeiro bloco de saída.
  • head lê o primeiro bloco e o escreve.
  • Supondo que haja linhas suficientes após as primeiras 10 correspondências (caso contrário, grep poderá terminar primeiro), eventualmente head terá impresso o número desejado de linhas. Neste momento, head sai.
  • Dependendo da velocidade relativa dos processos grep e head , grep pode ter acumulado alguns dados e ainda não ter sido impresso. No momento em que head exits, grep pode estar lendo entrada ou fazendo processamento interno e, nesse caso, continuará a fazê-lo.
  • Em breve, grep gravará os dados processados. Nesse ponto, ele receberá um SIGPIPE e morrerá.

É provável que grep processe um pouco mais de entrada do que o estritamente necessário, mas normalmente apenas alguns kilobytes:

  • head normalmente lê em blocos de alguns kilobytes (porque é mais eficiente do que emitir uma chamada de sistema read para cada byte - esse comportamento é chamado de buffering), portanto o restante do último pedaço após a última linha desejada é descartado.
  • Pode haver alguns dados em trânsito, pois os pipes têm um buffer associado gerenciado pelo kernel (geralmente 512 bytes). Esses dados serão descartados.
  • grep pode ter acumulado alguns dados que estão prontos para se tornar um pedaço de saída (buffer novamente). Ele receberá o SIGPIPE quando estiver tentando liberar seu buffer de saída.

Em suma, o sistema é projetado com precisão para que os utilitários de filtragem se comportem naturalmente de maneira eficiente. Os programas que precisam continuar quando o canal de saída é desligado devem dar o passo de ignorar o sinal SIGPIPE.

    
por 26.01.2012 / 01:25
3

Sortof, o pipeline funciona assim: ele primeiro executa o primeiro comando e depois o segundo comando no seu caso.

Isto é, vamos ter A|B como o comando dado. Então é incerto se A ou B começa primeiro. Eles podem começar exatamente no mesmo horário se houver várias CPUs. Um tubo pode conter uma quantidade indefinida, mas finita de dados.

Se B tentar ler o pipe, mas nenhum dado estiver disponível, B esperará até que os dados cheguem. Se B estivesse lendo de um disco, B poderia ter o mesmo problema e precisar aguardar até que uma leitura de disco fosse concluída. Uma analogia mais próxima seria a leitura de um teclado. Lá, B precisaria aguardar um usuário digitar. Mas em todos esses casos, B iniciou uma operação de "leitura" e deve esperar até que ela termine. Mas se B for um comando de tal forma que precise apenas de saída parcial de A , depois de um certo ponto em que B s nível de entrada seja atingido A será eliminado pelo SIGPIPE

Se A tentar gravar no tubo e o tubo estiver cheio, A deve esperar que algum espaço no tubo se torne livre. A poderia ter o mesmo problema se estivesse gravando em um terminal. Um terminal tem controle de fluxo e pode moderar o ritmo dos dados. Em qualquer caso, para A , iniciou uma operação de "gravação" e aguardará até que a operação de gravação seja concluída.

A e B estão se comportando como coprocessos, embora nem todos os coprocessos estejam se comunicando com um canal. Nenhum deles está no controle total do outro.

    
por 25.01.2012 / 15:05
1

grep não tem controle direto do pipe (está apenas recebendo dados), e o pipe não tem controle direto de grep (está apenas enviando dados) ...

O que grep , ou qualquer outro programa, depende inteiramente da lógica interna desses programas. Se você disser grep via opções de linha de comando para fazer um exit-when-found inicial, então ele irá, caso contrário ele irá seguir até o final do arquivo procurando pelo padrão ...

O terminal também está bastante desconectado do funcionamento interno de grep e das ações de tubulação de shell ... O Terminal é basicamente apenas uma plataforma de lançamento e exibição de saída ...

    
por 25.01.2012 / 16:23