Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

Режим обработки обрабатывает определенные управляющие символы; например, по умолчанию ^U уничтожает (стирает) текущую строку, ^W стирает текущее слово, забой (^Н) или Delete — предыдущий символ, a ^R стирает и затем повторно набирает текущую строку. Каждое из этих управляющих действий может быть повторно назначено другом символу. Например, на многих терминалах символу DEL (код 127) назначается действие забоя.

16.1.1. Служебные функции терминалов

Иногда невозможно узнать, соответствует ли файловый дескриптор tty. Чаще всего это связано со стандартным дескриптором выходного файла. Программы, выводящие текст на стандартные

устройства, часто форматируются иначе при записи в канал, чем при отображении информации для пользователей. Например, в случае применения команды
ls
для получения списка файлов, она отобразит несколько колонок при простом запуске (удобнее читать человеку), но когда вы перенаправите ее вывод в другую программу, она отобразит по одному файлу в строке (удобнее читать программе). Запустите
ls
и
ls | cat
и почувствуйте разницу.

Определить, соответствует ли файловый дескриптор tty, можно с помощью функции

isatty
, принимающей файловый дескриптор в качестве своего аргумента и возвращающей 1, если дескриптор соответствует tty, и 0 в противном случае.

#include <unistd.h>

int isatty(int fd);

Функция

ttyname
предоставляет каноническое имя для терминала, ассоциированное с файловым дескриптором. В качестве аргумента она принимает любой файловый дескриптор, возвращая указатель в поток символов.

#include <unistd.h>

char *ttyname(int fd);

Поскольку поток символов расположен в статическом пространстве, потребуется сделать копию возвращенной строки перед повторным вызовом

ttyname
; эта функция не реентерабельна.
ttyname
возвращает
NULL
при любой ошибке, включая случай передачи файлового дескриптора, не ассоциированного с tty.

16.1.2. Управляющие терминалы

Каждый сеанс (см. главу 10) привязан к терминалу, с которого процессы сеанса получают свои входные данные и в который пересылают свои выходные данные. Этот терминал может быть локальной консолью машины, терминалом, подключенным через последовательный канал, либо псевдотерминалом, устанавливающим соответствия во внешнем окне или по всей сети (подробнее о псевдотерминалах читайте в конце этой главы). Терминал, к которому относится сеанс, называется управляющим терминалом (или управляющим tty) сеанса. Терминал может быть управляющим терминалом только в одном сеансе за раз.

Нормальные процессы не могут менять свои управляющие терминалы; это может делать только лидер сеанса. В Linux изменение управляющего терминала лидера сеанса не распространяется на другие процессы того же сеанса. Лидеры сеансов почти всегда устанавливают управляющий терминал при запуске до создания каких-либо дочерних процессов, чтобы гарантировать, что все процессы сеанса совместно используют один управляющий терминал.

Существуют два интерфейса для смены управляющего tty лидера сеанса. Первый реализуется с помощью нормальных системных вызовов

open
и
close
.

1. Закройте все файловые дескрипторы, относящиеся к текущему управляющему терминалу.

2. Откройте новый терминал без установки флага

O_NOCTTY
.

Второй метод включает вызовы

ioctl
на отдельных файловых дескрипторах, ссылающихся на старые и новые терминалы.

1. Установите флаг

TIOCNOTTY
на файловый дескриптор, привязанный к исходному управляющему tty (обычно
ioctl(0, TIOCNOTTY, NULL)
нормально работает). Это разрывает соединение между сеансом и tty.

2. Установите флаг

TIOCSCTTY
на файловый дескриптор, привязанный к новому управляющему tty. Это устанавливает новый управляющий tty.

Терминал, используемый сеансом, отслеживает то, какая группа процессов считается группой процессов переднего плана. Процессам в этой группе разрешается читать и записывать в терминал, в то время как процессам в другой группе это не разрешено (более подробно о том, что происходит, когда фоновые процессы пытаются читать и производить запись в управляющий терминал, рассказывается в главе 15).

Функция

tcsetpgrp
позволяет процессу, работающему на терминале, сменить группу процессов переднего плана для этого терминала [108] .

int tcsetpgrp(int ttyfd, pid_t pgrp);

Первый параметр определяет tty, управляющая группа процессов которого изменяется, a

pgrp
является группой процессов, которую необходимо переместить на передний план. Процессы могут менять группу процессов переднего плана только для своего управляющего терминала. Если процесс, совершающий изменение, не принадлежит к группе процессов переднего плана на этом терминале, генерируется сигнал
SIGTTOU
, если только он не игнорируется или заблокирован [109] .

108

Реализации Unix старого типа предоставляли эту функцию с помощью

TIOCSPGRP ioctl
, до сих пор поддерживаемого Linux. Для сравнения,
tcsetpgrp
можно реализовать как
ioctl(ttyfd, TIOCSPGRP, &pgrp)
.

109

Более подробно о сигналах и их взаимодействии с управлением заданиями рассказывается в главе 12.

16.1.3. Принадлежность терминала

Существуют две системные базы данных, используемые для отслеживания зарегистрированных пользователей; utmp применяется для пользователей, зарегистрированных в данный момент, a wtmp является записью всех предыдущих регистраций со времени создания файла. Команда

who
использует базу данных utmp для отображения списка зарегистрированных пользователей, а команда
last
— базу данных wtmp для отображения списка пользователей, зарегистрированных в системе после регенерации базы данных wtmp. В системах Linux база данных utmp хранится в файле
/var/run/utmp
, а база данных wtmp — в файле
/var/log/wtmp
.

Программы, использующие tty для сеансов регистрации пользователей (независимо от того, ассоциируются ли они с графической регистрацией), должны обновлять эти две системные базы данных, пока пользователь явно не сделает иной запрос; например, некоторые пользователи не хотят, чтобы каждый сеанс оболочки, запускаемый ими в эмуляторе терминала в системе X Window, перечислялся как процесс входа. Добавляйте только интерактивные сеансы, поскольку utmp и wtmp не предназначены для регистрации автоматизированных программ. Любые tty, не являющиеся контролирующими терминалами, обычно в базы данных utmp и wtmp не добавляются.

Поделиться с друзьями: