Как битовые маски проверяются в fd_set, используемом в select? - PullRequest
2 голосов
/ 16 декабря 2011

Согласно этой статье опрос против выбора против событий :

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

Вот реализация fd_set (найдена в Советы: множественные приложения Структура fd_set битовый массив переполнение индекса

#ifndef FD_SETSIZE
#define FD_SETSIZE  1024
#endif
#define NBBY    8       /* number of bits in a byte */
typedef long    fd_mask;
#define NFDBITS (sizeof (fd_mask) * NBBY)   /* bits per mask */
#define howmany(x,y)    (((x)+((y)-1))/(y))
typedef struct _types_fd_set {
    fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} _types_fd_set;

#define fd_set _types_fd_set

Итак, в конце, fd_set это просто массив long. Также записано:

При вызове FD_SET бит устанавливается в 1 с использованием номера сокета в качестве индекса:

, что означает, что если я получил сокет с номером 5, элемент с индексом 5 будет выбран, а его первый бит будет переключен с 0 на 1. Поскольку select() использует 3 бита, я думаю, что другойдва бита предназначены для отправки и получения. Верно ли это? Почему select() использует long, когда ему нужно только 3 бита?

Также, как указано выше, poll() использует 64 бита для проверки. Почему poll нужно проверять каждый бит в pollfd структуре? Вот структура pollfd:

struct pollfd {
    int fd;         // the socket descriptor
    short events;   // bitmap of events we're interested in
    short revents;  // when poll() returns, bitmap of events that occurred
};

Общее количество битов в структуре составляет 64 бита, для 32-разрядного типа int и двух 16-Я знаю, что обычным способом проверки флага битов является использование оператора AND (&) для фильтрации другихнеактуальные биты.Относится ли это к этому делу?

Ответы [ 3 ]

4 голосов
/ 16 декабря 2011

poll () обычно использует 64 бита на дескриптор файла. В каждом вызове системного вызова poll (), таким образом, нужно намного больше копировать в пространство ядра. Небольшой выигрыш для избранных ().

Ошибка - если вы хотите отслеживать только один fd, poll (2) избавит вас от этих 64 битов, в то время как для select () вы должны скопировать до 12288 битов (3 набора по 4096 битов) обычно).

Также poll () поддерживает fd со значением, превышающим FD_SETSIZE.

4 голосов
/ 16 декабря 2011

Причина, по которой select() использует long s, заключается в кодировании многих битов в одно значение переменной.long может содержать 32 (или иногда 64, в наши дни) бита, как правило, что означает, что вы можете представить набор из 32 файлов, используя одно значение типа long.

«Три бита на файл»."исходит из трех различных значений fd_set, которые вы обычно используете для выбора как для чтения, записи, так и для исключений.Три значения long (при условии 32-разрядного long), 32 * 3 = 96 бит, но можно выбрать для всех трех условий для 32 различных файлов, тратя таким образом 3 бита на файл.Это предполагает, что вы select() для каждого из этих 32 файлов во всех трех наборах, что, я думаю, является, по крайней мере, несколько редким.

Поскольку poll представляет файловые дескрипторы напрямую, используя поле размером int, скореечем неявно индексом в битовый набор, он использует больше места.

В принципе, дизайн select() использует преимущество предположения, что файловые дескрипторы являются * маленькими * целыми числами, и что они выделяются из 0и выше.

3 голосов
/ 16 декабря 2011

Он не использует 1 long как таковой. Он использует битовое поле FD_SETSIZE битов, в данном случае 32 32-битных или 16 64-битных. Используя long, он позволяет использовать меньше операций с памятью на 64-битных машинах (которые широко распространены в Unix уже 20 лет). Они могли бы использовать обычный int, но тогда у них не было бы преимущества на 64-битных машинах. Это только вперед, думая.

Если вы использовали select для нескольких файловых дескрипторов, вам нужно место для всех файловых дескрипторов. Представьте, что вы хотите читать из 3 сокетов, из устройства SCSI и файла, а значения дескриптора файла соответственно 3, 7, 10, 12 и 67, как бы вы это представили? Используйте набор битов, где установлен бит с этим номером.

 00010001.00101000:00000000.00000000:00000000.00000000:00000000.00000000   00010000.00000000
    ^   ^   ^ ^                                                               ^
    0   0   1 1                                                               6 
    3   7   0 2                                                               7 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...