Por que Ctrl-D (EOF) sai do shell?

69

Você está literalmente "finalizando um arquivo" inserindo esta sequência de escape, ou seja, a sessão interativa do shell é vista como um fluxo de arquivos real pelo shell, como qualquer outro fluxo de arquivos? Se sim, qual arquivo?

Ou, o sinal Ctrl+ é Dapenas um espaço reservado que significa "o usuário terminou de fornecer entrada e você pode encerrar"?

Geeb
fonte
6
Para sua informação, no bash você pode fazer set -o ignoreeofpara mudar esse comportamento.
Keith
Eu tive o mesmo problema. Meu erro foi acidentalmente atribuir o atalho do perfil do konsole a "Ctrl + d". Não é o meu momento de maior orgulho.
Brian Simonsen

Respostas:

79

O ^Dcaractere (também conhecido como \04ou 0x4, END OF TRANSMISSION em Unicode) é o valor padrão para o eofparâmetro de caractere de controle especial do terminal ou driver do pseudo-terminal no kernel (mais precisamente da ttydisciplina de linha anexada ao serial ou pseudo- dispositivo tty ). Essa é a c_cc[VEOF]da termiosestrutura passado para os TCSETS / TCGETS ioctlum problemas para o dispositivo terminal de afetar o comportamento do condutor.

O comando típico que envia esses ioctlsé o sttycomando.

Para recuperar todos os parâmetros:

$ stty -a
velocidade 38400 baud; linhas 58; colunas 191; linha = 0;
intr = ^ C; sair = ^ \; apagar = ^ ?; matar = ^ U; eof = ^ D ; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^ Q; parar = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; proxima = ^ V; flush = ^ O;
min = 1; tempo = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

Esse eofparâmetro é relevante apenas quando o dispositivo terminal está no icanonmodo.

Nesse modo, o driver do terminal (não o emulador de terminal) implementa um editor de linhas muito simples , onde você pode digitar Backspacepara apagar um caractere, Ctrl-Uapagar toda a linha ... Quando um aplicativo lê no dispositivo do terminal, ele não vê nada até você pressiona o Returnponto em que read()retorna a linha completa, incluindo o último LFcaractere (por padrão, o driver do terminal também traduz o CRenviado pelo seu terminal Returnpara LF).

Agora, se você deseja enviar o que você digitou até agora sem pressionar Enter, é aí que você pode inserir o eofcaractere. Ao receber esse caractere do emulador de terminal, o driver do terminal envia o conteúdo atual da linha, para que o aplicativo que readestiver fazendo o recebimento o receba como está (e não inclua um LFcaractere à direita ).

Agora, se a linha atual estava vazia e desde que o aplicativo tenha lido completamente as linhas inseridas anteriormente, o readcaractere retornará 0.

Isso significa o fim do arquivo para o aplicativo (quando você lê um arquivo, você lê até que não haja mais nada a ser lido). É por isso que é chamado de eofpersonagem, porque enviá-lo faz com que o aplicativo veja que não há mais entrada disponível.

Agora, os shells modernos, quando solicitados, não configuram o terminal no icanonmodo porque implementam seu próprio editor de linha, que é muito mais avançado do que o driver de terminal incorporado. No entanto, em seu próprio editor de linha , para evitar confundir os usuários, eles dão ao ^Dpersonagem (ou qualquer que seja a eofconfiguração do terminal com alguns) o mesmo significado (para significar eof).

Stéphane Chazelas
fonte
Eu sabia que, depois que comecei a ler este comentário, ele foi escrito por Stephane :) Você, Stephane, é meu herói Bash e não estou sendo sarcástico. Eu adoraria almoçar com você e escolher seu cérebro, se você estiver em Nova York, eu estou comprando.
precisa
@GreggLeventhal. Obrigado. As chances de eu ir para Nova York tão cedo são muito pequenas.
Stéphane Chazelas
É EOT, mesmo em ASCII de 7 bits
Bananguin
9

CTRL_D é apenas um sinal dizendo que este é o fim de um fluxo de texto. Você não finaliza um arquivo com ele, finaliza seu fluxo de entrada digitando-o. CTRL_D também não representa nenhum caractere ou byte, como você pode descobrir com a ferramenta hexdump:

# cat >test.txt
asdf# hexdump -C test.txt 
00000000  61 73 64 66                                       |asdf|
00000004
# ll test.txt 
-rw-r--r-- 1 root root 4 Jan 21 11:55 test.txt
Thorsten Staerk
fonte
5
E a razão pela qual encerra o shell é que o shell é basicamente um processo que aceita entrada e faz coisas com ele. Quando você diz que não haverá mais entrada, não há mais nada para o shell fazer.
Jenny D
Percebo que a sequência EOF não está contida em, digamos, um arquivo de texto e é gerada pelo sistema operacional para relatar que não há mais dados para ler. Acho que realmente estou perguntando se a sessão do terminal interativo é vista como um fluxo de arquivos real pelo shell, como qualquer outro fluxo de arquivos.
Geeb
Apenas editei a pergunta original para esclarecer.
Geeb
2
Sim, o fluxo que vai para o bash é um fluxo de entrada como qualquer outro. CTRL_D sinaliza que o fluxo de entrada está no final e o bash pode sair.
precisa saber é o seguinte