web-dev-qa-db-fra.com

Pourquoi Ctrl-D (EOF) quitte-t-il le shell?

Êtes-vous littéralement en train de "terminer un fichier" en saisissant cette séquence d'échappement, c'est-à-dire que la session interactive du Shell est considérée comme un véritable flux de fichiers par le Shell, comme tout autre flux de fichiers? Si oui, quel fichier?

Ou, est le Ctrl+D signal juste un espace réservé qui signifie "l'utilisateur a fini de fournir une entrée et vous pouvez terminer"?

72
Geeb

Le caractère ^D (Également appelé \04 Ou 0x4, FIN DE TRANSMISSION en Unicode) est la valeur par défaut du paramètre de caractère de contrôle spécial eof du pilote de terminal ou pseudo-terminal dans le noyau (plus précisément de la discipline de ligne tty attachée au périphérique série ou pseudo-tty ). C'est le c_cc[VEOF] De la structure termios transmise aux TCSETS/TCGETS ioctl que l'on émet vers le terminal pour affecter le comportement du pilote.

La commande typique qui envoie ces ioctls est la commande stty.

Pour récupérer tous les paramètres:

 $ stty -a 
 vitesse 38400 bauds; rangées 58; colonnes 191; ligne = 0; 
 intr = ^ C; quitter = ^ \; effacer = ^ ?; kill = ^ U; eof = ^ D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^ Q; stop = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; lnext = ^ V; flush = ^ O; 
 min = 1; time = 0; 
 - parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts 
 - ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclcc -ixany -imaxbel iutf8 
 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 
 isig icanon iexten echo echoe echoe echok -echonl -noflsh -xcase -tostop - echoprt echoctl echoke 

Ce paramètre eof n'est pertinent que lorsque le terminal est en mode icanon.

Dans ce mode, le pilote de terminal (pas l'émulateur de terminal) implémente un éditeur de ligne très simple , où vous pouvez taper Backspace pour effacer un caractère, Ctrl-U pour effacer toute la ligne ... Lorsqu'une application lit à partir du terminal, elle ne voit rien tant que vous n'appuyez pas sur Return auquel point la read() renvoie la ligne complète incluant le dernier LF caractère (par défaut, le pilote de terminal traduit également le CR envoyé par votre terminal lors de Return à LF).

Maintenant, si vous voulez envoyer ce que vous avez tapé jusqu'à présent sans appuyer sur Enter, c'est là que vous pouvez saisir le caractère eof. À la réception de ce caractère de l'émulateur de terminal, le pilote de terminal soumet le contenu actuel de la ligne, de sorte que l'application faisant le read dessus il le recevra tel quel (et il n'inclura pas de caractère LF de fin).

Maintenant, si la ligne actuelle était vide, et à condition que l'application ait entièrement lu les lignes précédemment saisies, le read renverra 0 caractère.

Cela signifie fin de fichier pour l'application (lorsque vous lisez un fichier, vous lisez jusqu'à ce qu'il n'y ait plus rien à lire). C'est pourquoi il est appelé le caractère eof, car son envoi fait que l'application ne voit plus aucune entrée disponible.

Maintenant, les shells modernes, à leur invite, ne placent pas le terminal en mode icanon car ils implémentent leur propre éditeur de ligne , ce qui est beaucoup plus avancé que le pilote de terminal intégré. Cependant, dans leur propre éditeur de ligne , pour éviter de dérouter les utilisateurs, ils donnent le caractère ^D (Ou quel que soit le eof paramètre est avec certains) la même signification (pour signifier eof).

81
Stéphane Chazelas

CTRL_D est juste un signal disant que c'est la fin d'un flux de texte. Vous ne terminez pas un fichier avec lui, vous terminez votre flux d'entrée en le tapant. CTRL_D ne représente pas non plus de caractère ou d'octet comme vous pouvez le découvrir avec l'outil 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
9
Thorsten Staerk