Скачиваний:
21
Добавлен:
09.05.2014
Размер:
354.82 Кб
Скачать

Ioctl. Когда соответствующие критерии удовлетворены, программа обработки

прерываний строкового интерфейса возобновляет выполнение всех приостановлен-

ных процессов. Драйвер пересылает все символы из списка для хранения нест-

руктурированных вводных данных в канонический список и выполняет запрос про-

цесса на чтение, следуя тому же самому алгоритму, что и в случае работы в

каноническом режиме. Режим без обработки символов особенно важен в экран-

но-ориентированных приложениях, таких как экранный редактор vi, многие из

команд которого не заканчиваются символом возврата каретки. Например, коман-

да dw удаляет слово в текущей позиции курсора.

На Рисунке 10.17 приведена программа, использующая функцию ioctl для

сохранения текущих установок терминала для файла с дескриптором 0, что соот-

ветствует значению дескриптора файла стандартного ввода. Функция ioctl с ко-

мандой TCGETA приказывает

драйверу извлечь установки и сохранить их в структуре с именем savetty в ад-

ресном пространстве задачи. Эта команда часто используется для того, чтобы

определить, является ли файл терминалом или нет, поскольку она ничего не из-

меняет в системе: если она завершается неудачно, процессы предполагают, что

файл не является терминалом. Здесь же, процесс вторично вызывает функцию

Ioctl для того, чтобы перевести терминал в режим без обработки: он отключает

эхо-сопровождение ввода символов и готовится к выполнению операций чтения с

+----------------------------------------------------------------+

| #include |

| #include |

| 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; |

316

| 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-символьных блоков

+----------------------------------------------------------------+

| #include |

| |

| main() |

| { |

| register int i,n; |

| int fd; |

| char buf[256]; |

| |

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

| if((fd = open("/dev/tty",O_RDONLY|O_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 |

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

| n++; |

| } |

| } |

+----------------------------------------------------------------+

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

317

терминала по получении с терминала 5 символов, как минимум, или по прохожде-

нии 10 секунд с момента ввода первой порции символов. Когда процесс получает

сигнал о прерывании, он сбрасывает первоначальные параметры терминала и за-

вершается.

10.3.4 Опрос терминала

Иногда удобно производить опрос устройства, то есть считывать с него

данные, если они есть, или продолжать выполнять обычную работу - в противном

случае. Программа на Рисунке 10.18 иллюстрирует этот случай: после открытия

терминала с параметром "no delay" (без задержки) процессы, ведущие чтение с

него, не приостановят свое выполнение в случае отсутствия данных, а вернут

управление немедленно (см. алгоритм terminal_read, Рисунок 10.15). Этот ме-

тод работает также, если процесс следит за множеством устройств: он может

открыть каждое устройство с параметром "no delay" и опросить всех из них,

ожидая поступления информации с каждого. Однако, этот метод растрачивает вы-

числительные мощности системы.

В системе BSD есть системная функция select, позволяющая производить оп-

рос устройства. Синтаксис вызова этой функции:

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

где nfds - количество выбираемых дескрипторов файлов, а rfds, wfds и efds

указывают на двоичные маски, которыми "выбирают" дескрипторы открытых фай-

лов. То есть, бит 1 << fd (сдвиг на 1 разряд влево значения дескриптора фай-

ла) соответствует установке на тот случай, если пользователю нужно выбрать

этот дескриптор файла. Параметр timeout (тайм-аут) указывает, на какое время

следует приостановить выполнение функции select, ожидая поступления данных,

например; если данные поступают для любых дескрипторов и тайм-аут не закон-

чился, select возвращает управление, указывая в двоичных масках, какие деск-

рипторы были выбраны. Например, если пользователь пожелал приостановиться до

момента получения данных по дескрипторам 0, 1 или 2, параметр rfds укажет на

двоичную маску 7; когда select возвратит управление, двоичная маска будет

заменена маской, указывающей, по каким из дескрипторов имеются готовые дан-

ные. Двоичная маска wfds выполняет похожую функцию в отношении записи деск-

рипторов, а двоичная маска efds указывает на существование исключительных

условий, связанных с конкретными дескрипторами, что бывает полезно при рабо-

те в сети.

Соседние файлы в папке материалы к собеседованию