Qual é a diferença em usar Ctrl + D e Ctrl + C para encerrar o comando cat?

1

Eu tenho os dois arquivos de teste a seguir:

test1 test2

Ambos estão em branco. Agora eu emito os seguintes comandos:

$ cat > test1  

Digite

This is a test file

Digite

Ctrl + D

$ cat > test2

Digite

This is another test file

Digite

^C

Ctrl + C

$

Agora eu verifico o conteúdo dos dois arquivos

$ cat test1
This is a test file
$ cat test2
This is another test file
$

Então, existe alguma diferença real no resultado se usarmos os dois métodos acima para alcançar o mesmo resultado?

    
por Sonevol 18.07.2017 / 19:34

2 respostas

2

Quando o comando cat está em execução, o terminal está no modo de entrada canônica . Isto significa, em resumo, que a disciplina de linha do terminal está lidando com edição de linha, e está respondendo a todos os caracteres especiais configurados para o terminal (visível e configurável com o% comandostty).

O comando cat é simplesmente read() ing de sua entrada padrão até que uma chamada read() retorne zero bytes lidos, a convenção POSIX para atingir o final do arquivo.

Os terminais não têm realmente um "fim". Mas há uma circunstância em que read() de um dispositivo terminal retorna zero bytes. Quando a disciplina de linha recebe o caractere especial "EOF", seja lá o que for que esteja configurado no momento, isso fará com que read() retorne com o que estiver no buffer de edição nesse ponto. Se o buffer de edição estiver vazio, isso retorna zero bytes lidos de read() , fazendo com que cat seja encerrado.

cat também sai em resposta a sinais cujas ações padrão são para finalizar o processo. A disciplina de linha também gera sinais em resposta a caracteres especiais. Os caracteres especiais "INTR" e "QUIT" fazem com que os sinais INT e QUIT sejam enviados para o processo de primeiro plano (grupo), que será / contém o processo cat . A ação padrão desses sinais é finalizar o processo cat .

O que leva às diferenças observáveis:

  • Ctrl + D só tem esta ação quando é o caractere especial do EOT. Isto é geralmente o caso, mas não é necessariamente o caso. Da mesma forma, Ctrl + C só tem sua ação quando é o caractere especial INTR.
  • Ctrl + D não fará com que cat termine quando a linha não estiver de fato vazia no momento. Uma interrupção gerada por Ctrl + C irá, no entanto.
  • Uma implementação ingênua de cat na linguagem C bloqueará a saída padrão do buffer se ela for direcionada para um arquivo, como na pergunta. Em teoria, isso poderia levar a que as linhas em buffer e ainda não fossem perdidas se cat fosse terminado por SIGINT .

    Na prática, as bibliotecas BSD e GNU C implementam um modo de buffering que não é descrito no C ou Padrões de linguagem C ++. Saída padrão quando redirecionado para arquivo ou pipe é smart buffered . É bloqueado em bloco; exceto que sempre que a biblioteca C se encontra prestes a read() o início de uma nova linha a partir de qualquer descritor de arquivo que esteja aberto para um dispositivo de terminal, ele libera a saída padrão. (As bibliotecas BSD e GNU C não implementam exatamente a mesma semântica e fazem mais do que isso, estritamente falando, mas esse comportamento é um subconjunto comum.) Assim, um sinal de interrupção não causará saída em buffer perdida quando cat for construído no topo de tal biblioteca C.

  • Obviamente, se cat fizer parte de um pipeline de comando, algum outro outro processo poderia armazenar em buffer os dados, a jusante de cat , antes que esses dados alcancem um arquivo de saída. Então, novamente, quando a disciplina de linha envia SIGINT , que (por padrão) encerra todos os processos no pipeline, os dados de entrada armazenados em buffer e ainda não gravados serão perdidos; Considerando que terminar cat normalmente com o caractere especial "EOF" fará com que o pipeline termine normalmente, com todos os dados passando para o processo downstream antes de ele receber uma indicação EOF de its read() de sua entrada padrão.

Observe que isso tem muito pouca relação com o que acontece quando o shell interativo está lendo uma linha de entrada de você. Quando o seu shell está esperando pela entrada, o terminal está no modo de entrada não-canônico , em qual modo a disciplina de linha não faz nenhum tratamento especial de caracteres especiais. Como o seu shell trata Ctrl + D e Ctrl + C é inteiramente da biblioteca de edição de entrada que o seu shell usa (libedit, readline ou ZLE) e como essa biblioteca de edição foi configurada (com associações de teclas e semelhantes).

Leitura adicional

por 18.07.2017 / 23:06
2

CTRL + C é um sinal de interrupção. Isso irá parar o comando.

CTRL + D é o final do arquivo ou exit() . Quando você digitou CTRL + D , ele saiu do comando por causa do fim do arquivo. Se você digitar CTRL + C no seu shell, nada acontecerá. No entanto, se você digitar CTRl + D , ele sairá do seu Shell atual na maioria dos sistemas.

    
por 18.07.2017 / 19:41

Tags