Bash while loop e lendo do pipe

3

Eu tenho um programa de linha de comando do Windows que estou executando em um script Bash no Ubuntu via wine. O script Bash basicamente se parece com isso:

wine myprogram.exe | while read line
do
   # Process line
done

Agora, desde que eu escrevi myprogram.exe, eu sei de fato que ele apenas gera dados o mais rápido possível. Alguém pode me explicar como o Bash while loop é capaz de processar os dados no caso de meu programa ser lançado mais rápido do que o while loop pode manipular? Existe alguma feitiçaria acontecendo nos bastidores onde o agendador do kernel fará o myprogram.exe dormir se ele produzir muitos dados? Qualquer um? Atualmente estou inclinado a ser magia negra.

    
por Magnus 19.10.2012 / 19:59

3 respostas

5

Primeiro, o programa pode fazer seu próprio buffer de saída. Às vezes, isso é chamado de “armazenamento em buffer stdio ” após o nome do componente da biblioteca que executa essa tarefa em C: as funções como putc , fputs , fprintf , etc., declarado em stdio.h . Em caso afirmativo, produzirá saída em rajadas, normalmente de alguns kilobytes (quando a saída é um terminal, o padrão é liberar o buffer em cada caractere de nova linha).

Em algum momento, o programador ou a função de biblioteca subjacente chama write explicitamente. Isso solicita que o kernel grave os dados especificados no pipe. O kernel pode decidir gravar todos ou parte dos dados. Como o arquivo é um pipe, o kernel copiará os dados na área de buffer do pipe. Se o buffer de tubulação estiver cheio, a chamada de sistema write bloqueia até que haja espaço: seu programa (ou mais precisamente, o encadeamento que chamou write , caso haja vários encadeamentos no nível do kernel) não retomará a execução até a chamada para write retorna.

(É possível, mas improvável nesta situação, que o programa tenha definido o descritor de arquivos do canal como não- blocking Se este for o caso, se o kernel determinar que não pode copiar nenhum dado, ele retornará o controle para o programa, a chamada do sistema write retornará 0. Um programa que faz tal bloqueio não chamadas do sistema normalmente chamam select ou poll ou epoll em um loop para bloquear até que um dos descritores de arquivo com os quais ele está se comunicando esteja pronto para entrada ou saída.)

O fato de o programa estar bloqueado durante uma chamada de sistema não está relacionado à escolha do algoritmo de escalonamento. Em sua essência, qualquer programador distingue entre os tópicos prontos , que podem ser fornecidos Tempo de CPU e aguardando threads, o que não é possível. A essência de um planejador é escolher um encadeamento pronto e deixá-lo rodar até que o encadeamento faça uma chamada de sistema (o que coloca o encadeamento em estado de espera) ou ocorra algum evento assíncrono (na prática, um processador interrupt ). Durante o processamento de uma chamada de sistema, pode ser que um encadeamento que estava até então bloqueado esteja pronto, por exemplo, porque esse encadeamento estava em uma chamada write e o kernel agora pôde entregar os dados dessa chamada. Algumas coisas podem bloquear um thread pronto, por exemplo, um sinal para pausar ( SIGSTOP ) . O agendador mantém algum tipo de lista pronta para decidir qual thread agendar a seguir: uma lista de threads que estão prontos (geralmente é muito mais complicado do que uma simples lista em um agendador do mundo real).

    
por 20.10.2012 / 00:30
2

É chamado de pipe. Execute man 7 pipe e você aprenderá tudo sobre como os canos funcionam.

Editado para adicionar: Em resumo, a saída do comando wine é coletada em um buffer. Quando o buffer está cheio e o vinho tenta escrever mais, o processo do vinho é interrompido pelo kernel. Quando o espaço se torna disponível no buffer (ou seja, quando o loop while lê a partir dele), o processo interrompido é reavivado e é permitido continuar. Este é o algoritmo clássico de buffer limitado, mas no mundo Unix / Linux é geralmente chamado de pipe. É muito popular e poderoso, e eu recomendo aprender tudo sobre isso.

    
por 19.10.2012 / 20:09
1

Nah, não há magia negra (bem, não desta vez, pelo menos). Ele apenas usa seu cache e buffers no fluxo de saída.

    
por 19.10.2012 / 20:02