Читаем Разработка приложений в среде Linux. Второе издание полностью

Три промежуточных параметра — readfds, writefds и exceptfds — определяют, за какими файловыми дескрипторами необходимо следить. Каждый параметр — это указатель на fd_set, структуру данных, позволяющую процессу определить произвольное количество файловых дескрипторов[74]. Ею манипулируют с помощью перечисленных ниже макросов.

FD_ZERO(fd_set * fds);Очищает fds — в наборе не содержатся файловые дескрипторы. Этот макрос используется для инициализации структур fd_set.
FD_SET(intfd, fd_set * fds);Добавляет fd к fd_set.
FD_CLR(intfd, fd_set * fds);Удаляет fd из fd_set.
FD_ISSET(int fd, fd_set * fds);Возвращает true, если fd содержится в установленном fds.

Первый набор файловых дескрипторов select(), readfds, содержит перечень файловых дескрипторов, вызывающих возврат вызова select(), когда они готовы для чтения[75] или (для каналов и сокетов) когда процесс на другом конце файла закрыл его. Когда любой файловый дескриптор в writefds готов к записи, select() возвращается, exceptfds содержит файловые дескрипторы для слежения за исключительными условиями. В Linux (так же, как и в Unix) это происходит только при поступлении внешних данных в сетевое подключение. В качестве любого из них можно указать NULL, если тот или иной тип события вас не интересует.

Окончательный параметр, timeout, определяет, насколько долго (в миллисекундах) вызову select() необходимо ожидать какого-либо события. Это указывает на struct timeval, которая выглядит следующим образом.

#include

struct timeval {

 int tv_sec; /* секунды */

 int tv_usec; /* микросекунды */

};

Первый элемент — tv_sec — это количество оставшихся секунд, a tv_usec — это количество оставшихся микросекунд. Если значением timeout является NULL, select() блокируется до следующего события. Если он указывает на struct timeval, содержащую 0 в обоих элементах, вызов select() не блокируется. Он обновляет наборы файловых дескрипторов, чтобы определить, какой файловый дескриптор в настоящее время готов для чтения или записи, а затем немедленно возвращается.

Первый параметр, numfds, вызывает наибольшие трудности. Он задает количество файловых дескрипторов (начиная с файлового дескриптора 0), которое может быть определено с помощью fd_sets. Еще один (и, возможно, более легкий) способ поведения numfds намного лучше максимального файлового дескриптора select()[76].

Поскольку Linux обычно позволяет каждому процессу иметь до 1024 файловых дескрипторов, numfds избавляет ядро от необходимости просмотра всех 1024 файловых дескрипторов, которые может содержать каждая структура fd_set, что улучшает показатели производительности.

После возврата три структуры fd_set содержат файловые дескрипторы с задержкой входных данных, на которые можно произвести запись или которые находятся в исключительном состоянии. Вызов select() в Linux возвращает общее количество элементов, установленных в трех структурах fd_set, 0 в случае тайм-аута вызова либо -1 в случае ошибки. Однако многие системы Unix считают определенные файловые дескрипторы в возвращаемом значении только один раз, даже если они находятся как в readfds, так и в writefds, поэтому в целях переносимости лучше совершать проверку только тогда, когда возвращаемое значение больше 0. Если возвращаемое значение равно -1, не думайте, что структуры fd_set остаются незатронутыми. Linux обновляет их только в случае, если select() возвращает значение больше 0, однако некоторые системы Unix демонстрируют иное поведение.

Еще одним параметром, связанным с переносимостью, является timeout. Ядра Linux[77] обновляют его, чтобы отобразить количество времени, оставшегося до тайм-аута вызова select(), но большинство других систем Unix его не обновляют[78]. Однако другие системы не обновляют тайм-аут с целью соответствия более привычной реализации.

Для переносимости устраните зависимость от поведения и явно настройте структуру timeout перед вызовом select().

Теперь рассмотрим несколько примеров применения select(). Для начала используем select() без связи с файлами, создав вторичный вызов sleep().

#include

#include

int usecsleep(int usees) {

 struct timeval tv;

 tv.tv_sec = 0;

 tv.tv_usec = useсs;

 return select(0, NULL, NULL, NULL, &tv);

}

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

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

1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

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

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

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

Книга посвящена верстке и макетированию в программе Adobe InDesign CS3. Помимо того что в ней описываются возможности программы, рассматриваются также принципы и традиции верстки, приводятся примеры решения типичных задач. Все это позволит читателю не только овладеть богатым инструментарием программы, но и грамотно применять его.Материал книги разделен на логические части: теоретические сведения, инструментарий программы, решение задач, – а также рассчитан на два уровня подготовки читателей – начинающих и опытных пользователей, что выгодно отличает книгу от других изданий. Это позволит применять ее как новичкам для знакомства с программой, так и пользователям со стажем для пополнения своих знаний.

Владимир Гавриилович Завгородний , Владимир Завгородний

Программирование, программы, базы данных / Программное обеспечение / Книги по IT