Определить, соответствует ли файловый дескриптор tty, можно с помощью функции isatty()
, принимающей файловый дескриптор в качестве своего аргумента и возвращающей 1, если дескриптор соответствует tty, и 0 в противном случае.
#include
int isatty(int fd);
Функция ttyname()
предоставляет каноническое имя для терминала, ассоциированное с файловым дескриптором. В качестве аргумента она принимает любой файловый дескриптор, возвращая указатель в поток символов.
#include
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] Реализации Unix старого типа предоставляли эту функцию с помощью TIOCSPGRP ioctl() , до сих пор поддерживаемого Linux. Для сравнения, tcsetpgrp() можно реализовать как ioctl(ttyfd, TIOCSPGRP, &pgrp) .
.
int tcsetpgrp(int ttyfd, pid_t pgrp);
Первый параметр определяет tty, управляющая группа процессов которого изменяется, a pgrp
является группой процессов, которую необходимо переместить на передний план. Процессы могут менять группу процессов переднего плана только для своего управляющего терминала. Если процесс, совершающий изменение, не принадлежит к группе процессов переднего плана на этом терминале, генерируется сигнал SIGTTOU
, если только он не игнорируется или заблокирован [109] Более подробно о сигналах и их взаимодействии с управлением заданиями рассказывается в главе 12.
.
16.1.3. Принадлежность терминала
Существуют две системные базы данных, используемые для отслеживания зарегистрированных пользователей; utmpприменяется для пользователей, зарегистрированных в данный момент, a wtmpявляется записью всех предыдущих регистраций со времени создания файла. Команда who
использует базу данных utmp для отображения списка зарегистрированных пользователей, а команда last
— базу данных wtmp для отображения списка пользователей, зарегистрированных в системе после регенерации базы данных wtmp. В системах Linux база данных utmp хранится в файле /var/run/utmp
, а база данных wtmp — в файле /var/log/wtmp
.
Читать дальше