¿Por qué Ctrl-D (EOF) sale del shell?

69

¿Está literalmente "terminando un archivo" al ingresar esta secuencia de escape, es decir, la sesión de shell interactiva es vista como un flujo de archivo real por el shell, como cualquier otro flujo de archivos? Si es así, ¿qué archivo?

¿O la señal Ctrl+ es Dsolo un marcador de posición que significa "el usuario ha terminado de proporcionar información y usted puede finalizar"?

Geeb
fuente
66
FYI, en bash puedes hacer set -o ignoreeofpara cambiar ese comportamiento.
Keith
Yo tuve el mismo problema. Mi error fue que accidentalmente asigné el acceso directo al perfil de konsole a "Ctrl + d". No es mi momento de mayor orgullo.
Brian Simonsen

Respuestas:

79

El ^Dcarácter (también conocido como \04o 0x4, FIN DE LA TRANSMISIÓN en Unicode) es el valor predeterminado para el eofparámetro de carácter de control especial del controlador de terminal o pseudo-terminal en el núcleo (más precisamente de la ttydisciplina de línea asociada al serial o pseudo- dispositivo tty ). Ese es el c_cc[VEOF]de la termiosestructura pasada a los TCSETS / TCGETS ioctluno cuestiones al dispositivo terminal para afectar el comportamiento del conductor.

El comando típico que envía esos ioctlses el sttycomando.

Para recuperar todos los parámetros:

$ stty -a
velocidad 38400 baudios; filas 58; columnas 191; línea = 0;
intr = ^ C; salir = ^ \; borrar = ^ ?; matar = ^ U; eof = ^ D ; eol = <undef>; eol2 = <undef>; swtch = <undef>; inicio = ^ Q; detener = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; lnext = ^ V; rubor = ^ O;
min = 1; tiempo = 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

Ese eofparámetro solo es relevante cuando el dispositivo terminal está en icanonmodo.

En ese modo, el controlador de terminal (no el emulador de terminal) implementa un editor de línea muy simple , donde puede escribir Backspacepara borrar un carácter, Ctrl-Upara borrar toda la línea ... Cuando una aplicación lee desde el dispositivo terminal, no ve nada hasta presiona Returnen qué punto read()devuelve la línea completa, incluido el último LFcarácter (de forma predeterminada, el controlador de terminal también traduce el CRenviado por su terminal Returna LF).

Ahora, si desea enviar lo que escribió hasta ahora sin presionar Enter, ahí es donde puede ingresar el eofcarácter. Al recibir ese carácter del emulador de terminal, el controlador de terminal envía el contenido actual de la línea, de modo que la aplicación que lo haga readlo recibirá tal cual (y no incluirá un LFcarácter final ).

Ahora, si la línea actual estaba vacía, y siempre que la aplicación haya leído completamente las líneas ingresadas anteriormente, readdevolverá el carácter 0.

Eso significa el final del archivo para la aplicación (cuando lees desde un archivo, lees hasta que no hay nada más que leer). Es por eso que se llama el eofcarácter, porque enviarlo hace que la aplicación vea que no hay más entradas disponibles.

Ahora, los shells modernos, a su solicitud, no configuran el terminal en icanonmodo porque implementan su propio editor de línea, que es mucho más avanzado que el controlador de terminal incorporado. Sin embargo, en su propio editor de línea , para evitar confundir a los usuarios, le dan al ^Dpersonaje (o lo que sea la eofconfiguración del terminal con algunos) el mismo significado (para significar eof).

Stéphane Chazelas
fuente
Una vez que comencé a leer este comentario, supe que estaba escrito por Stephane :) Tú, Stephane, eres mi héroe Bash, y no estoy siendo sarcástico. Me encantaría almorzar contigo y elegir tu cerebro si alguna vez estás en Nueva York, estoy comprando.
Gregg Leventhal
@GreggLeventhal. Gracias. Sin embargo, las posibilidades de que vaya a Nueva York en cualquier momento son bastante escasas.
Stéphane Chazelas
Es EOT incluso en ASCII de 7 bits
Bananguin
9

CTRL_D es solo una señal que dice que este es el final de una secuencia de texto. No termina un archivo con él, finaliza su flujo de entrada al escribirlo. Además, CTRL_D no representa ningún carácter o byte, como puede descubrir con la herramienta 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
fuente
55
Y la razón por la que termina el shell es que el shell es básicamente un proceso que acepta entradas y hace cosas con ellas. Cuando le dices que no va a llegar más información, no hay nada más que pueda hacer el shell.
Jenny D
Me doy cuenta de que la secuencia EOF no está contenida, por ejemplo, en un archivo de texto, y es generada por el sistema operativo para informar que no hay más datos para leer. Creo que lo que realmente estoy preguntando es si la sesión de terminal interactiva es vista como una secuencia de archivos real por el shell, como cualquier otra secuencia de archivos.
Geeb
Acabo de editar la pregunta original para aclarar.
Geeb
2
Sí, la secuencia que va a bash es una secuencia de entrada como cualquier otra. CTRL_D indica que la secuencia de entrada está finalizando y que bash puede salir.
Thorsten Staerk