Чому Ctrl-D (EOF) виходить з оболонки?


68

Ви буквально "закінчуєте файл", вводячи цю послідовність запуску, тобто інтерактивний сеанс оболонки розглядається як реальний потік файлу оболонкою, як і будь-який інший потік файлів? Якщо так, то який файл?

Або сигнал Ctrl+ є Dлише заповнювачем місця, що означає, що "користувач закінчив надавати введення, і ви можете припинити"?



6
FYI, в баші ви можете зробити, set -o ignoreeofщоб змінити таку поведінку.
Кіт

У мене була така ж проблема. Моя помилка полягала в тому, що я випадково призначив ярлик профілю konsole "Ctrl + d". Не моя горда мить.
Брайан Сімонсен

Відповіді:


78

^DСимвол (також відомий як \04або 0x4, Кінець передачі в Unicode) є значенням за замовчуванням для eofспеціального параметра керуючих символів терміналу або псевдо-термінального драйвера в ядрі (точніше з ttyлінії дисципліна прикріплена до послідовного або псевдо- tty пристрій ). Ось c_cc[VEOF]така termiosструктура, передана TCSETS / TCGETS, ioctlодна проблема видає термінальному пристрою, щоб вплинути на поведінку драйвера.

Типовою командою, яка надсилає їх, ioctlsє sttyкоманда.

Щоб отримати всі параметри:

$ stty -a
швидкість 38400 бод; рядки 58; колонки 191; рядок = 0;
intr = ^ C; кинути = ^ \; стерти = ^ ?; вбити = ^ U; eof = ^ D ; eol = <undef>; eol2 = <undef>; swtch = <undef>; старт = ^ Q; стоп = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; наступний = ^ V; змивання = ^ О;
хв = 1; час = 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

Цей eofпараметр є актуальним лише тоді, коли термінальний пристрій у icanonрежимі.

У такому режимі драйвер терміналу (а не емулятор терміналу) реалізує дуже простий редактор рядків , де ви можете ввести Backspaceстирання символу, Ctrl-Uвидалити всю лінію ... Коли програма читає з термінального пристрою, вона нічого не бачить, поки ви натискаєте Returnна який момент read()повертає повну рядок , включаючи останній LFсимвол (за замовчуванням, драйвер терміналу також переводить CRрозсилається термінал на Returnдо LF).

Тепер, якщо ви хочете надіслати те, що ви ввели до цього часу, не натискаючи Enter, саме там ви можете ввести eofсимвол. Отримавши цей символ від емулятора терміналу, драйвер терміналу подає поточний вміст рядка, так що програма, що робить readйого, отримає його таким, який є (і він не буде містити LFсимволу трейлінгу ).

Тепер, якщо поточний рядок був порожнім і за умови, що програма буде повністю прочитати раніше введені рядки, readповернеться 0 символів.

Це означає, що кінець файлу в програмі (коли ви читаєте з файлу, ви читаєте, поки більше нічого не можна прочитати). Ось чому його називають eofсимволом, оскільки його надсилання змушує програму бачити, що більше немає вводу.

Тепер, сучасні оболонки, за їх підказкою, не встановлюють термінал у icanonрежимі, оскільки вони реалізують власний редактор рядків, який значно досконаліший, ніж вбудований драйвер терміналу. Однак у власному редакторі рядків , щоб не плутати користувачів, вони надають ^Dсимволу (або будь-якому встановленню терміналу eofз деякими) те саме значення (для позначення eof).


Я знав, як тільки я почав читати цей коментар, що його написав Стефан :) Ти, Стефане, мій герой Баша, і я не є саркастичним. Я хотів би пообідати з вами і забрати ваш мозок, якщо ви коли-небудь бували в Нью-Йорку, я купую.
Грегг Левенталь

@GreggLeventhal. Дякую. Шанси мене поїхати в Нью-Йорк в будь-який час незабаром досить тонкий.
Стефан Шазелас

Це навіть у 7-
бітовому

9

CTRL_D - це лише сигнал про те, що це кінець текстового потоку. Ви не закінчуєте файл із ним, ви закінчуєте вхідний потік, ввівши його. Також CTRL_D не означає жодного символу чи байта, як ви можете дізнатися з інструментом 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

5
І причиною того, що вона закінчується оболонкою, є те, що оболонка - це, в основному, процес, який приймає вхід і виконує завдання. Коли ви скажете, більше не буде надходити вхід, оболонки більше нічого не робити.
Дженні Д

Я розумію, що послідовність EOF не міститься, скажімо, текстовим файлом, і генерується ОС, щоб повідомити, що більше немає даних для читання. Я думаю, що я справді запитую, чи інтерактивний сеанс терміналу розглядається як справжній потік файлів оболонкою, як і будь-який інший файловий потік.
Geeb

Щойно відредагував оригінальне запитання, щоб уточнити.
Geeb

2
так, потік, який йде в bash, є вхідним потоком, як і будь-який інший. CTRL_D сигналізує про те, що вхідний потік знаходиться в його кінці і баш може вийти.
Thorsten Staerk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.