Читаем Архитектура операционной системы UNIX полностью

На Рисунке 10.17 приведена программа, использующая функцию ioctl для сохранения текущих установок терминала для файла с дескриптором 0, что соответствует значению дескриптора файла стандартного ввода. Функция ioctl с командой TCGETA приказывает драйверу извлечь установки и сохранить их в структуре с именем savetty в адресном пространстве задачи. Эта команда часто используется для того, чтобы определить, является ли файл терминалом или нет, поскольку она ничего не изменяет в системе: если она завершается неудачно, процессы предполагают, что файл не является терминалом. Здесь же, процесс вторично вызывает функцию ioctl для того, чтобы перевести терминал в режим без обработки: он отключает эхо-сопровождение ввода символов и готовится к выполнению операций чтения с терминала по получении с терминала 5 символов, как минимум, или по прохождении 10 секунд с момента ввода первой порции символов. Когда процесс получает сигнал о прерывании, он сбрасывает первоначальные параметры терминала и завершается.

#include ‹signal.h›

#include ‹termio.h›

struct termio savetty;

main() {

 extern sigcatch();

 struct termio newtty;

 int nrd;

 char buf[32];

 signal(SIGINT, sigcatch);

 if (ioctl(0, TCGETA, &savetty) == -1) {

  printf("ioctl завершилась неудачно: нет терминала\n");

  exit();

 }

 newtty = savetty;

 newtty.c_lflag &= ~ICANON; /* выход из канонического режима */

 newtty.c_lflag &= ~ECHO; /* отключение эхо-сопровождения*/

 newtty.c_cc[VMIN] = 5; /* минимум 5 символов */

 newtty.c_cc[VTIME] = 100; /* интервал 10 секунд */

 if (ioctl(0,TCSETAF, &newtty) == -1) {

  printf("не могу перевести тер-л в режим без обработки\n");

  exit();

 }

 for(;;) {

  nrd = read(0, buf, sizeof(buf));

  buf[nrd] = 0;

  printf("чтение %d символов %s'\n", nrd, buf);

 }

}

sigcatch() {

 ioctl(0, TCSETAF, &savetty);

 exit();

}

Рисунок 10.17. Режим без обработки — чтение 5-символьных блоков

<p id="_11_3_4">10.3.4 Опрос терминала</p>

Иногда удобно производить опрос устройства, то есть считывать с него данные, если они есть, или продолжать выполнять обычную работу — в противном случае. Программа на Рисунке 10.18 иллюстрирует этот случай: после открытия терминала с параметром "no delay" (без задержки) процессы, ведущие чтение с него, не приостановят свое выполнение в случае отсутствия данных, а вернут управление немедленно (см. алгоритм terminal_read, Рисунок 10.15). Этот метод работает также, если процесс следит за множеством устройств: он может открыть каждое устройство с параметром "no delay" и опросить всех из них, ожидая поступления информации с каждого. Однако, этот метод растрачивает вычислительные мощности системы.

#include ‹fcntl.h›

main() {

 register int i, n;

 int fd;

 char buf[256];

 /* открытие терминала только для чтения с опцией "no delay" */

 if ((fd = open("/dev/tty", O_RDONLYO_NDELAY)) == -1) exit();

 n = 1;

 for(;;) {  /* всегда */

  for (i = 0; i ‹ n; i++);

  if (read(fd, buf, sizeof(buf)) › 0) {

   printf("чтение с номера %d\n", n);

   n--;

  }

  else n++; /* ничего не прочитано; возврат вследствие "no delay" */

 }

}

Рисунок 10.18. Опрос терминала

В системе BSD есть системная функция select, позволяющая производить опрос устройства. Синтаксис вызова этой функции:

select(nfds, rfds, wfds, efds, timeout)

Перейти на страницу:

Все книги серии Серия книг по программному обеспечению издательства prentice hall

Похожие книги