Как работает ввод текста в терминале linux?
Всем привет, кто нибудь может объяснить хотя бы примерно, как работает ввод текста в терминале с клавиатуры?
Не получается нагуглить подобное да и не знаю даже как правильно сформулировать запрос. В общем, что именно в линуксе занимается считыванием данных с клавиатуры и отображением их в терминале? Командные оболочки такие как bash и sh насколько я знаю этим не занимаются. Они лишь принимают ввод из stdin и выполняют команды.
Допустим я написал какую-то программу на С и там прописал что-то типа fgets(buffer, 20, stdin);
И когда я выполняю эту программу, то на этой строчке терминал переходит в режим считывания данных с клавиатуры. Но как это работает не понятно. В stdin может быть как файл так и данные с клавиатуры. Это как-то на уровне ядра происходит? Где система проверяет если stdin это файл, то просто считать данные из файла, а если это какое-то устройство типа клавиатуры, то запустить какой нить процесс считывания с клавиатуры. Помогите плиз.






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

29.07.2019 05:25:40
В stdin может быть как файл так и данные с клавиатуры. Это как-то на уровне ядра происходит?
Процесс назначения stdin и stdout для конкретной программы не является "одноступенчатым". На самом деле, события развиваются как-то так:
- Вы подходите к терминалу (их может быть много разных) и вводите логин/пароль.
- Демон логина проверяет Ваши права и (если всё ОК) сообщает ядру о входе пользователя с Вашим конкретным ID.
- Ядро, по ID ищет в файле /etc/passwd информацию о Вас.
- Найдя эту инфу, ядро устанавливает заданный для Вас текущий каталог и запускает тот варианта shell, который указан в Ваших данных. При запуске shell ему передаётся имя устройства /dev/tty... с которого вы залогинились.
Это устройство становится stdin и stdout для Вашего экземпляра shell. Первая часть назначения завершена. Дальше события развиваются следующим образом:
- shell печатает на stdout приглашение ввода - промпт.
- Вы печатает нечто вроде my_prog и нажимаете Enter.
- shell считывает имя программы, и выполняет системные вызовы fork и execve.
- Ядро выделяем память для процесса и копирует(!!!) туда всё программное окружение, включая (!) дескрипторы файлов 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.