Como o Bash canaliza grandes quantidades de dados?

3

Digamos que você queira reproduzir o conteúdo de um arquivo realmente grande , mas deseja exibi-lo alguns bits por vez. Digamos que um fosse fazer o seguinte:

$ cat /dev/sda1 | less

Como programador de linguagens como Java e ActionScript, quando olho para esse código, imagino que Bash primeiro execute o comando cat /dev/sda1 (carregando everything o comando retorna para a RAM) e, em seguida, executando o comando less que tem acesso a uma "pseudo-variável" realmente grande representada como - .

É assim que o Bash faz as coisas (o que significa que o comando é uma idéia muito ruim se o arquivo é maior que a quantidade de RAM do seu sistema e você deve usar outro comando) ou tem uma maneira de otimizar a tubulação de grandes quantidades de dados?

    
por IQAndreas 31.10.2014 / 05:21

3 respostas

5

Não, não carrega tudo na memória, isso seria uma maneira impraticável de projetar isso. Ele usa buffers para armazenar em buffer a saída do lado esquerdo do pipe e, em seguida, conecta esses buffers à entrada do comando no lado direito do pipe.

A página de manual man 7 pipe tem todos os detalhes, assim como este outro U & LQ & A intitulado: Qual é o tamanho do buffer do pipe?

    
por 31.10.2014 / 05:59
1

read irá bloquear até que os dados estejam disponíveis, e a gravação irá bloquear ou falhar caso o pipe esteja cheio. Existem alguns parâmetros como PIPE_BUF , PIPE_SIZE e O_NONBLOCK que desempenham um papel fundamental no pipe.

O valor de PIPE_BUF pode ser determinado via 'ulimit -a'. Está definido nos limites.h. O PIPE_BUF controla o tamanho garantido para gravação atômica . Isso ajuda a criar aplicativos multithread seguros.

O PIPE_SIZE depende do tamanho da página. No kernel 2.4, era equivalente ao tamanho de uma página (4KB). No entanto versões após 2.6 são mapeadas para uma matriz de 16 páginas (64 KB). Isso é definido no arquivo pipe_fs_i.h como PIPE_BUFFERS (16). Versões posteriores do kernel têm fcntl com F_SETPIPE_SZ permitindo aumento no tamanho da página.

O O_NONBLOCK permite executar gravações parciais e diferidas. No entanto, se O_NONBLOCK estiver habilitado, mas se o número de bytes a serem gravados no canal for maior que PIPE_BUF, a gravação falhará no caso se o campo estiver cheio, senão com base no valor de retorno da gravação, ele será intercalado com dados de outros processos .

    
por 31.10.2014 / 13:24
0

Tente usar a opção -B , ela usa apenas o buffer de 64k.

cat /dev/sda1 | less -B

De man less :

-B or --auto-buffers By default, when data is read from a pipe, buffers are allocated automatically as needed. If a large amount of data is read from the pipe, this can cause a large amount of memory to be allocated. The -B option disables this automatic allocation of buffers for pipes, so that only 64K (or the amount of space specified by the -b option) is used for the pipe. Warning: use of -B can result in erroneous display, since only the most recently viewed part of the file is kept in memory; any earlier data is lost.

    
por 12.12.2016 / 14:49

Tags