First, the entire thing prints only after the 5 second sleep so from that I deduced the output from the kernel to the terminal is line buffered.
Não, a saída do seu programa para o kernel está com buffer de linha. Esse é o comportamento padrão para stdio
quando stdout
é um terminal. Adicione a chamada setbuf(stdout, NULL)
para desativar o buffer de saída para stdout
. Veja setbuf(3)
.
- Since the
\b\b
goes back two spaces, to the position ofl
then similar to howl
was replaced byh
, theo
should have been replaced by\n
. Why wasn't it?
Como o caractere de nova linha apenas move o cursor (e rola a tela), ele não é impresso como um caractere visível que ocuparia o lugar de um glifo no terminal. Se assumirmos que tomaria o lugar de um glifo, como seria?
- if I input something into the very same program, and press Backspace, it erases the last character, but not for the output. Why?
Bem, o que acontece quando você digita depende do modo em que o terminal está. Aproximadamente, ele pode estar no modo "cozido" usual, no qual o próprio terminal fornece edição de linha elementar (manipula backspaces); ou em um modo "bruto", onde todos os pressionamentos de tecla vão para o aplicativo, e cabe ao aplicativo decidir o que fazer com eles e o que enviar em resposta. O modo cozinhado geralmente acompanha o "eco local", no qual o terminal (local para o usuário) imprime os caracteres à medida que são digitados. No modo raw, o aplicativo geralmente cuida de ecoar os caracteres digitados, para ter controle total sobre o que é visível.
Ver, por exemplo, esta questão para discussão sobre os modos de terminal: Qual é a diferença entre um driver de dispositivo "cru" e um "cozido"?
Se você executar, e. cat
, o terminal estará no modo cozido (o padrão) e lidará com a edição da linha. Atingir, por exemplo, x Backspace Ctrl-D resultará em cat
apenas lendo a entrada vazia, sinalizando o final da entrada. Você pode verificar isso com strace
. Mas se você executar um shell Bash interativo, ele manipulará o backspace por si só e exibirá o que considerar apropriado para fazer o que o usuário espera, ou seja, limpar um caractere.
Aqui está parte da saída para strace -etrace=read,write -obash.trace bash
, depois de entrar na seqüência mencionada x Backspace Ctrl-D :
read(0, "x", 1) = 1
write(2, "x", 1) = 1
read(0, "7", 1) = 1
write(2, "[K", 4) = 4
read(0, "", 1) = 1
Primeiro, Bash read
se write
s x
, enviando para o terminal. Em seguida, ele lê o backspace (código de caractere 0177 em octal ou 127 em decimal) e exibe o caractere de backspace (octal 010, decimal 8 (*) ) que move o cursor de volta e exibe a sequência de controle para limpar o final da linha, <ESC>[K
. O último é o
Ctrl-D
, que é usado pelo Bash para sair do programa.
(* na entrada, Ctrl-H
teria o código de caractere decimal 8. Backspace é o mesmo ou 127 como aqui, dependendo novamente de como o terminal está configurado.)
Em comparação, o mesmo experimento com cat
mostra apenas uma única leitura de zero bytes, a condição "fim do arquivo". O fim do arquivo pode significar que um pipe ou socket conectado está sendo fechado, um final real do arquivo ou Ctrl-D
sendo recebido de um terminal no modo cozido:
read(0, "", 131072) = 0
Em particular, cat
não vê o x
, nem o backspace, nem o código real para Ctrl-D
: eles são manipulados pelo terminal. Qual pode ser o driver de terminal virtual no kernel; um terminal físico real sobre uma conexão serial ou algo semelhante; ou um emulador de terminal como o xterm rodando na mesma máquina ou na extremidade remota de uma conexão SSH. Não importa para o software do espaço do usuário.