Читаем Основы программирования в Linux полностью

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

Системный вызов select позволяет программе ждать прибытия данных (или завершения вывода) одновременно на нескольких низкоуровневых файловых дескрипторах. Это означает, что программа эмулятора терминала может блокироваться до тех пор, пока у нее не появится работа. Аналогичным образом сервер может иметь дело с многочисленными клиентами, ожидая запросы одновременно на многих открытых сокетах.

Функция select оперирует структурами данных fd_set, представляющими собой множества открытых файловых дескрипторов. Для обработки этих множеств определен набор макросов:

#include #include

void FD_ZERO(fd_set *fdset);

void FD_CLR(int fd, fd_set *fdset);

void FD_SET(int fd, fd_set *fdset);

int FD_ISSET(int fd, fd_set *fdset);

Как и предполагается в соответствии с их именами, макрос FD_ZERO инициализирует структуру fd_set пустым множеством, FD_SET и FD_CLR задают и очищают элементы множества, соответствующего файловому дескриптору, переданному как параметр fd, а макрос FD_ISSET возвращает ненулевое значение, если файловый дескриптор, на который ссылается fd, является элементом структуры fd_set, на которую указывает параметр fdset. Максимальное количество файловых дескрипторов в структуре типа fd_set задается константой FD_SETDIZE.

Функция select может также использовать значение для времени ожидания, чтобы помешать бесконечной блокировке. Это значение задается с помощью структуры struct timeval. Она определена в файле sys/time.h и содержит следующие элементы:

struct timeval {

 time_t tv_sec; /* Секунды */

 long tv_usec;  /* Микросекунды */

}

Тип time_t, определенный в файле sys/types.h, — целочисленный. Системный вызов select объявляется следующим образом:

#include

#include

int select(int nfds, fd_set *readfds, fd_set *writefds,

 fd_set *errorfds, struct timeval *timeout);

Вызов select позволяет проверить, не готов ли хотя бы один из множества файловых дескрипторов к чтению или записи, или находится ли в ожидании из-за состояния ошибки и может быть заблокирован до момента готовности одного из дескрипторов.

Аргумент nfds задает количество проверяемых файловых дескрипторов, имеются в виду дескрипторы от 0 до nfds-1. Каждое из трех множеств дескрипторов может оказаться пустым указателем, тогда связанный с ним тест не выполняется.

Функция select вернет управление, если какой-либо из дескрипторов в множестве readfds готов к чтению, какой-нибудь дескриптор из множества writefds готов к записи или у одного из дескрипторов множества errorfd есть состояние ошибки. Если ни одно из условий не соблюдается, select вернет управление после промежутка времени, заданного timeout. Если параметр timeout — пустой указатель и нет активности на сокетах, вызов может быть заблокирован на неопределенное время.

Когда select возвращает управление программе, множества дескрипторов будут модифицированы для того, чтобы указать на готовые к чтению или записи или имеющие ошибки дескрипторы. Для их проверки следует использовать макрос FD_ISSET, позволяющий определить, какие дескрипторы требуют внимания. Можно изменить значение timeout для того, чтобы показать время, остающееся до следующего превышения времени ожидания, но такое поведение не задано стандартом X/Open. При превышении времени ожидания все множества дескрипторов будут очищены.

Вызов select возвращает общее количество дескрипторов в модифицированных множествах. В случае сбоя он вернет -1 и установит значение переменной errno, описывающее ошибку. Возможные ошибки — EBADF для неверных дескрипторов, EINTR для возврата из-за прерывания и EINVAL для некорректных значений параметров nfds или timeout.

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

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

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT