16.1.2. Управляющие терминалы
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].