Читаем Linux API. Исчерпывающее руководство полностью

В качестве результата функция select() возвращает одно из следующих значений.

• -1 свидетельствует об ошибке: EBADF или EINTR. Первая говорит о том, что один из файловых дескрипторов в группе readfds, writefds или exceptfds является недействительным (например, неоткрытым). Вторая сигнализирует о прерывании вызова обработчиком сигнала (как отмечалось в разделе 21.5, вызов select() в этой ситуации никогда не перезапускается автоматически).

• 0 означает, что время ожидания вызова истекло до того, как один из файловых дескрипторов стал готовым. В таком случае все возвращаемые наборы будут пустыми.

• Положительное значение говорит о готовности одного или нескольких файловых дескрипторов и соответствует их количеству. В данной ситуации следует проверить каждый возвращаемый набор (используя макрос FD_ISSET()), чтобы узнать, какие события ввода/вывода имели место. Если один и тот же дескриптор входит сразу в несколько наборов, то учитывается в каждом из них и считается готовым к более чем одному событию. Иными словами, вызов select() возвращает общее количество файловых дескрипторов, помеченных как готовые во всех трех наборах.

Пример программы

Применение вызова select() демонстрируется на примере листинга 59.1. С помощью аргументов командной строки можно указать время ожидания и файловые дескрипторы, которые мы хотим отслеживать. Первый параметр соответствует аргументу timeout вызова select() (в секундах). Если указать знак минус (—), то аргументу timeout будет передано значение NULL, что приведет к перманентной блокировке. Каждый следующий аргумент командной строки обозначает номер файлового дескриптора, за которым нужно наблюдать; за ним идут буквы, описывающие проверяемые операции. Букв может быть только две: r (готовность к чтению) и w (готовность к записи).

Листинг 59.1. Мониторинг нескольких файловых дескрипторов с помощью вызова select()

altio/t_select.c

#include

#include

#include "tlpi_hdr.h"

static void

usageError(const char *progName)

{

fprintf(stderr, "Usage: %s {timeout|-} fd-num[rw]…\n", progName);

fprintf(stderr, " — means infinite timeout; \n");

fprintf(stderr, " r = monitor for read\n");

fprintf(stderr, " w = monitor for write\n\n");

fprintf(stderr, " e.g.: %s — 0rw 1w\n", progName);

exit(EXIT_FAILURE);

}

int

main(int argc, char *argv[])

{

fd_set readfds, writefds;

int ready, nfds, fd, numRead, j;

struct timeval timeout;

struct timeval *pto;

char buf[10]; /* Достаточно большой для хранения "rw\0" */

if (argc < 2 || strcmp(argv[1], "-help") == 0)

usageError(argv[0]);

/* Время ожидания для select() указывается в argv[1] */

if (strcmp(argv[1], "-") == 0) {

pto = NULL; /* Бесконечное время ожидания */

} else {

pto = &timeout

timeout.tv_sec = getLong(argv[1], 0, "timeout");

timeout.tv_usec = 0; /* Без микросекунд */

}

/* Обрабатываем остальные аргументы, чтобы сформировать

наборы файловых дескрипторов */

nfds = 0;

FD_ZERO(&readfds);

FD_ZERO(&writefds);

for (j = 2; j < argc; j++) {

numRead = sscanf(argv[j], "%d%2[rw]", &fd, buf);

if (numRead!= 2)

usageError(argv[0]);

if (fd >= FD_SETSIZE)

cmdLineErr("file descriptor exceeds limit (%d)\n", FD_SETSIZE);

if (fd >= nfds)

nfds = fd + 1; /* Записываем максимум fd +1 */

if (strchr(buf, 'r')!= NULL)

FD_SET(fd, &readfds);

if (strchr(buf, 'w')!= NULL)

FD_SET(fd, &writefds);

}

/* Все аргументы сформированы; теперь вызываем select() */

ready = select(nfds, &readfds, &writefds, NULL, pto);

/* Игнорируем исключительные события */

if (ready == -1)

errExit("select");

/* Выводим результат выполнения select() */

printf("ready = %d\n", ready);

for (fd = 0; fd < nfds; fd++)

printf("%d: %s%s\n", fd, FD_ISSET(fd, &readfds)? "r": "",

FD_ISSET(fd, &writefds)? "w": "");

if (pto!= NULL)

printf("timeout after select(): %ld.%03ld\n",

(long) timeout.tv_sec, (long) timeout.tv_usec / 1000);

exit(EXIT_SUCCESS);

}

altio/t_select.c

Использование программы из листинга 59.1 демонстрируется в следующей сессии командной строки. В первом примере мы делаем запрос на мониторинг ввода в файловом дескрипторе 0 со временем ожидания 10 секунд:

$ ./t_select 10 0r

Нажимаем Enter, чтобы введенная строка была доступна в файловом дескрипторе 0

ready = 1

0: r

timeout after select(): 8.003

Отображается следующее приглашение командной строки

Как видите, вызов select() определил, что готовым к чтению был один файловый дескриптор с номером 0. Мы также видим обновление значения аргумента timeout. Последняя строчка вывода содержит только приглашение командной строки; оно выводится, так как программа t_select не прочитала символ новой строки, сделавший файловый дескриптор 0 готовым. Следовательно, он был прочитан командной оболочкой, которая в ответ вывела еще одно приглашение.

В следующем примере мы опять следим за вводом в файловом дескрипторе 0, но на этот раз время ожидания равно 0:

$ ./t_select 0 0r

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

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

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

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