Как работает ввод текста в терминале linux?

Как работает ввод текста в терминале linux?

26.07.2019 02:05:38 Просмотров 30 Источник

Всем привет, кто нибудь может объяснить хотя бы примерно, как работает ввод текста в терминале с клавиатуры?

Не получается нагуглить подобное да и не знаю даже как правильно сформулировать запрос. В общем, что именно в линуксе занимается считыванием данных с клавиатуры и отображением их в терминале? Командные оболочки такие как bash и sh насколько я знаю этим не занимаются. Они лишь принимают ввод из stdin и выполняют команды.

Допустим я написал какую-то программу на С и там прописал что-то типа fgets(buffer, 20, stdin);

И когда я выполняю эту программу, то на этой строчке терминал переходит в режим считывания данных с клавиатуры. Но как это работает не понятно. В stdin может быть как файл так и данные с клавиатуры. Это как-то на уровне ядра происходит? Где система проверяет если stdin это файл, то просто считать данные из файла, а если это какое-то устройство типа клавиатуры, то запустить какой нить процесс считывания с клавиатуры. Помогите плиз.

У вопроса есть решение - Посмотреть?

https://ru.stackoverflow.com/questions/1006942/%d0%9a%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82-%d0%b2%d0%b2%d0%be%d0%b4-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%b0-%d0%b2-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb%d0%b5-linux#comment1706985_1006942
Тут есть ответ на английском, пример полностью подойдет. stackoverflow.com/questions/1312922/…
https://ru.stackoverflow.com/questions/1006942/%d0%9a%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82-%d0%b2%d0%b2%d0%be%d0%b4-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%b0-%d0%b2-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb%d0%b5-linux#comment1707062_1006942
большая часть (если не все) из выдвинутых вами гипотез не соответствуют окружающей действительности (нет у терминала никакого «режима считывания», в stdin могут быть только байты, никакой дополнительный процесс кроме вашего не запускается, ну и т.д. и т.п.). начните с начала и далее по списку и ссылкам.
https://ru.stackoverflow.com/questions/1006942/%d0%9a%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82-%d0%b2%d0%b2%d0%be%d0%b4-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%b0-%d0%b2-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb%d0%b5-linux#comment1707084_1006942
Спасибо за ссылки, вторая вроде то, что нужно. Вроде стало понятно, что редактированием вводимого текста занимается драйвер в ядре, а не отдельные программы. Понять бы еще как этот ввод включается. Я запускаю в терминале программу, она что-то выводит на экран, в этот момент я не могу печатать. Когда я начинаю читать данные из stdin, процесс останавливается и включается ввод. Я ввожу текст и нажимаю enter и введенная строка попадает в программу, выполнение продолжается. Программа не знает откуда эти данные пришли, из файла или с клавиатуры. Но в случае с клавиатурой кто-то включает ввод, но кто
https://ru.stackoverflow.com/questions/1006942/%d0%9a%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82-%d0%b2%d0%b2%d0%be%d0%b4-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%b0-%d0%b2-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb%d0%b5-linux#comment1707343_1006942
в этот момент я не могу печатать — кстати, вполне можете. кто ж вам помешает?
https://ru.stackoverflow.com/questions/1006942/%d0%9a%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82-%d0%b2%d0%b2%d0%be%d0%b4-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%b0-%d0%b2-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb%d0%b5-linux#comment1707457_1006942
Спасибо, кажется разобрался. Печать действительно работает всегда. Просто некоторые программы насколько я узнал, могу переводить режим ввода в "сырой/неканоничный" и сами уже управляют вводом.

Ответы - Как работает ввод текста в терминале linux? / Как работает ввод текста в терминале linux?

Sergey

29.07.2019 05:25:40

В stdin может быть как файл так и данные с клавиатуры. Это как-то на уровне ядра происходит?

Процесс назначения stdin и stdout для конкретной программы не является "одноступенчатым". На самом деле, события развиваются как-то так:

  1. Вы подходите к терминалу (их может быть много разных) и вводите логин/пароль.
  2. Демон логина проверяет Ваши права и (если всё ОК) сообщает ядру о входе пользователя с Вашим конкретным ID.
  3. Ядро, по ID ищет в файле /etc/passwd информацию о Вас.
  4. Найдя эту инфу, ядро устанавливает заданный для Вас текущий каталог и запускает тот варианта shell, который указан в Ваших данных. При запуске shell ему передаётся имя устройства /dev/tty... с которого вы залогинились.

Это устройство становится stdin и stdout для Вашего экземпляра shell. Первая часть назначения завершена. Дальше события развиваются следующим образом:

  1. shell печатает на stdout приглашение ввода - промпт.
  2. Вы печатает нечто вроде my_prog и нажимаете Enter.
  3. shell считывает имя программы, и выполняет системные вызовы fork и execve.
  4. Ядро выделяем память для процесса и копирует(!!!) туда всё программное окружение, включая (!) дескрипторы файлов stdin и stdout

Таким образом, Ваше приложение наследует в качестве стандартных устройств ввода/вывода тот самый терминал, с которого Вы залогинились. Но, возможно, что Ваша команда имеет вид:

 > my_prog < my_stdin.txt

Тогда shell, выполняя запуск Вашего приложения, проверит существование my_stdin.txt, откроет этот файл на чтение и передаст дескриптор этого уже открытого файла Вашему приложению на месте stdin.

Ваше приложение может выяснить, откуда оно выполняет ввод, с помощью системных вызовов как-то так:

struct stat *sb;

fstat(stdin, &sb);
if ((sb.st_mode & S_IFMT) == S_IFREG) {
    /* обработка обычного файла */
}

Сам процесс ввода/выода для stdin выполняется драйвером соответствующего типа: терминала, дисковой файловой системы, СОМ-порта и т.д. Именно там выполняется необходимое буферирование, копирование и всё остальное. Прикладная программа имеет полное право совсем не знать, откуда идёт ввод.

Всё сказанное относится и к stdout.

Закрыть X