Почему Ctrl-D (EOF) выходит из оболочки?

69

Вы буквально «заканчиваете файл», вводя эту escape-последовательность, т.е. является ли сеанс интерактивной оболочки воспринимается оболочкой как реальный файловый поток, как и любой другой файловый поток? Если да, то какой файл?

Или сигнал Ctrl+ Dявляется просто заполнителем, который означает, что «пользователь завершил ввод данных, и вы можете завершить работу»?

Geeb
источник
6
К вашему сведению, в bash вы можете set -o ignoreeofизменить это поведение.
Кит
У меня такая же проблема. Моя ошибка заключалась в том, что я случайно назначил ярлык профиля konsole на «Ctrl + d». Не мой гордый момент.
Брайан Симонсен

Ответы:

79

Символ ^D(также известный как \04или 0x4, END OF TRANSMISSION в 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; lnext = ^ V; флеш = ^ O;
мин = 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 echo 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. Благодарю. Вероятность того, что я скоро приеду в Нью-Йорк, довольно мала.
Стефан
Это EOT даже в 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 сигнализирует о том, что входной поток заканчивается и bash может выйти.
Торстен Стэрк