Вход/Регистрация
Разработка приложений в среде Linux. Второе издание
вернуться

Троан Эрик В.

Шрифт:

retcode = ioctl(fd, VT_OPENQRY, &vtnum);

if ((retcode < 0) || (vtnum == -1)) {

 perror("myapp: нет доступных виртуальных терминалов");

 /* выполнить соответствующее действие */

}

Если в настоящее время используется менее 63 VC, и все из них заняты, то ядро автоматически выделяет память для новой VC [152] .

Для запуска переключения на другую VC (например, на ту свободную консоль, которую вы только что обнаружили) используется команда управления вводом-выводом

VT_ACTIVATE
. Если нужно подождать до тех пор, пока консоль не станет активной, применяется команда
VT_WAITACTIVE
. Смена консоли может занять некоторое время, возможно, несколько секунд. Это объясняется тем, что активизируемая консоль может находиться в графическом режиме, при этом содержимое экрана нужно реконструировать из памяти, выбрать из буфера обмена или восстановить каким-то другим способом, отнимающим немало времени [153] .

152

В большинстве остальных систем с виртуальными консолями или терминалами динамическое распределение для них не производится.

153

Отдельные системы (но не Linux) инициируют автоматическое переключение, если вызывается консоль, которая не исполняется в текущий момент.

ioctl(fd, VT_ACТIVATE, vtnum);

ioctl(fd, VT_WAITACTIVE, vtnum);

Для осуществления контроля над переключениями VC или для получения уведомлений о подобных переключениях необходимо предусмотреть надежные обработчики сигналов с

sigaction
, как обсуждалось в главе 12. Здесь мы применяем
SIGUSR1
и
SIGUSR2
; если нужно, вы можете использовать любые другие два сигнала, которые не предназначены для других целей (например,
SIGPROF
и
SIGURG
). Просто убедитесь, что выбранные вами сигналы удовлетворяют перечисленным ниже критериям.

• Они не требуются остальным системным функциям, особенно это касается тех сигналов, которые не могут быть перехвачены или проигнорированы.

• Они нигде не используются в вашем приложении для других целей.

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

SIGPOLL
и
SIGIO
(определения смотрите в
/usr/include/asm/signal.h
, либо ограничьте себя использованием сигналов из табл. 12.1).

void relsig(int signo) {

 /* выполнить соответствующее действие для освобождения VC */

}

void acqsig(int signo) {

 /* выполнить соответствующее действие для запроса VC */

}

void setup_signals(void) { struct sigaction sact;

 /* He маскировать никаких сигналов в то время,

* когда активизированы данные обработчики. */

 sigemptyset(&sact.sa_mask);

 /* Здесь может понадобиться добавление вызовов sigaddset,

* если существуют сигналы, которые нужно маскировать

* при переключении VC. */

 sact.flags = 0;

 sact.sa_handler = relsig;

 sigaction(SIGUSR1, &sact, NULL);

 sact.sa_handler = acqsig;

 sigaction(SIGUSR2, &sact, NULL);

}

После этого потребуется изменить стандартный режим VC (

mode
) с
VT_AUTO
на
VT_PROGRESS
, пока консоль уведомляется об обработчиках сигналов путем установки
relsig
и
acqsig
.

void control_vc_switching(int fd) {

 struct vt_mode vtmode;

 vtmode.mode = VT_PROCESS;

 vtmode.waitv = 1;

 vtmode.relsig = SIGUSR1;

 vtmode.acqsig = SIGUSR2;

 vtmode.frsig = 0;

 ioctl(fd, VT_SETMODE, &vtmode);

}

Обработчики сигналов, которые вызываются тогда, когда консоль находится в режиме

VT_PROCESS
, не должны соглашаться на переключение. Говоря более точно, обработчик
relsig
может отклонить разрешение на переключение VC. Обработчик
acqsig
, как правило, управляет процессом передачи консоли, но существует вероятность того, что он инициирует переключение на другую консоль. Будьте внимательны при кодировании обработчиков сигналов, чтобы избежать вызова любых нереентерабельных библиотечных функций. POSIX.1 устанавливает, что функции, перечисленные в табл. 12.2, являются реентерабельными. Значит, вы должны считать все остальные функции нереентерабельными, особенно, если хотите написать переносимую программу. Обратите внимание, в частности, на то, что
malloc
и
printf
являются нереентерабельными.

Ниже приведены примеры функций

relsig
и
acqsig
, выполняющих полезную работу. Особо следует отметить, что для функции
relsig
вызов
VT_RELDISP
является обязательным, тогда как для
acqsig
вызов
VT_RELDISP
рекомендуется только ради переносимости.

void relsig (int signo) {

 if (change_vc_ok) {

/* Разрешено переключение VC */

save_state;

ioctl(fd, VT_RELDISP, 1);

 } else {

/* Запрещено переключение VC */

ioctl(fd, VT_RELDISP, 0);

 }

}

void acqsig (int signo) {

 restore_state;

 ioctl(fd, VT_RELDISP, VT_ACKACQ);

}

Теперь вы в состоянии реализовать код функций

change_vc_ok
,
save_state
и
restore_state
.

  • Читать дальше
  • 1
  • ...
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: