Операционная система UNIX. Руководство программиста

Работа с несколькими терминалами сразу


Curses-программа может выводить данные сразу на несколько терминалов. Это может оказаться полезным при разработке программ, которые представляют собой один процесс и обращаются к одной базе данных, например, игр для нескольких участников.

Писать программы, работающие с несколькими терминалами, - дело нелегкое, и подпрограммы curses не решают всех возникающих при этом проблем. Например, сами программы, а не подпрограммы библиотеки, должны определять имена файлов для терминалов и типы этих терминалов. Стандартный способ с использованием переменной окружения $TERM не срабатывает, поскольку каждый процесс может знать только о своем собственном окружении.

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

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


Ссылки на терминал в curses-программе имеют тип *SCREEN. Новый терминал инициализируется путем обращения к newterm (type, outfd, infd). newterm возвращает указатель на новый терминал, type - это цепочка символов, содержащая тип используемого терминала. outfd является указателем на файл [*FILE, stdio(3S)], который используется для вывода на терминал, а infd указывает на файл для ввода с терминала. Вызов newterm() заменяет обычное обращение к initscr(), которое расширяется в newterm (getenv ("TERM"), stdout, stdin).

Для изменения текущего терминала необходимо вызвать set_term (sp), где sp указывает на терминал, который должен стать текущим. set_term() возвращает указатель на терминал, который был текущим на момент ее вызова.

Важно понять, что каждый терминал будет иметь свои собственные режимы работы и окна. Каждый терминал должен быть проинициализирован соответствующим вызовом newterm(). Для каждого терминала отдельно должны быть установлены режимы работы, например, cbreak() или noecho(). Равным образом для каждого терминала отдельно должны вызываться endwin() и refresh(). Ниже изображен типичный сценарий рассылки сообщения на несколько терминалов.

for (i=0; i<nterm; i++) { set_term (terms[i]); mvaddstr (0, 0, "Важное сообщение"); refresh (); }

Более подробный пример см. в программе two раздела Примеры программ, работающих с curses.




Содержание раздела