Чтение онлайн

на главную - закладки

Жанры

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

Троан Эрик В.

Шрифт:

25: fds[0].events = POLLIN;

26: fds[1].events = POLLIN;

27:

28: /* пока наблюдаем за одним из fds[0] или fds[1] */

29: while (fds[0].events || fds[1].events ) {

30: if (poll(fds, 2, 0) < 0) {

31: perror("poll");

32: return 1;

33: }

34:

35: /* проверить, какой из файловых дескрипторов

36: готов для чтения из него */

37: for (i = 0; i < 2; i++) {

38: if (fds[i].revents) {

39: /* fds[i] готов для чтения, двигаться дальше... */

40: rc = read(fds[i].fd, buf, sizeof(buf) - 1);

41: if (rc < 0) {

42: perror("read");

43: return 1;

44: } else if (!rc) {

45: /*
этот канал закрыт, не пытаться

46: читать из него снова */

47: fds[i].events = 0;

48: } else {

49: buf[rc] = '\0';

50: printf("чтение : %s", buf);

51: }

52: }

53: }

54: }

55:

56: return 0;

57: }

13.1.3. Мультиплексирование с помощью

select

Системный вызов

poll
был изначально представлен как часть Unix-дерева System V. Усилиями разработчиков BSD та же основная проблема была решена похожим способом — предоставлением системного вызова
select
.

#include <sys/select.h>

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

 fd_set * exceptfds, struct timeval * timeout);

Три промежуточных параметра —

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

74

Это похоже на тип

sigset_t
, используемый для шаблонов сигналов.

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
, если тот или иной тип события вас не интересует.

75

Когда сетевой сокет прослушивается (

listen
) и готов к приему (
accept
), считается,
что он готов к считыванию для целей
select
; информацию о сокетах можно найти в главе 17.

Окончательный параметр,

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

#include <sys/time.h>

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
, что улучшает показатели производительности.

76

Если сравнить это с параметром

numfds
для
poll
, то можно понять, почему возникают затруднения.

После возврата три структуры

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
.

77

Кроме некоторых экспериментальных ядер серии 2.1.

78

Когда Линус Торвальдс впервые реализовал

select
, неспособность ядра BSD обновлять
timeout
была отмечена как ошибка на man-странице для
select
. Вместо написания ошибочного кода Линус решил "исправить" эту ошибку. К сожалению, комитеты по стандартам одобрили поведение BSD.

Поделиться:
Популярные книги

Свадьба по приказу, или Моя непокорная княжна

Чернованова Валерия Михайловна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Свадьба по приказу, или Моя непокорная княжна

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Вадбольский

Никитин Юрий Александрович
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Вадбольский

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания

Таня Гроттер и магический контрабас

Емец Дмитрий Александрович
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Таня Гроттер и магический контрабас

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

Кодекс Крови. Книга ХI

Борзых М.
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХI

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Возвышение Меркурия. Книга 16

Кронос Александр
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 16

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Потусторонний. Книга 1

Погуляй Юрий Александрович
1. Господин Артемьев
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Потусторонний. Книга 1