Системные вызовы select()
и pselect()
изменяют свои аргументы (аргументы 'fd_set *
'), поэтому входное значение сообщает системе, какие файловые дескрипторы проверять, а возвращаемые значения сообщают программист, какие файловые дескрипторы в настоящее время используются.
Если вы собираетесь вызывать их несколько раз для одного и того же набора файловых дескрипторов, вам необходимо убедиться, что у вас есть свежая копия дескрипторов для каждого вызова. Очевидный способ сделать это - использовать структурную копию:
fd_set ref_set_rd;
fd_set ref_set_wr;
fd_set ref_set_er;
...
...code to set the reference fd_set_xx values...
...
while (!done)
{
fd_set act_set_rd = ref_set_rd;
fd_set act_set_wr = ref_set_wr;
fd_set act_set_er = ref_set_er;
int bits_set = select(max_fd, &act_set_rd, &act_set_wr,
&act_set_er, &timeout);
if (bits_set > 0)
{
...process the output values of act_set_xx...
}
}
( Отредактировано для удаления неправильных ссылок struct fd_set
- как указано 'R ..'. )
Мой вопрос:
- Существуют ли платформы, на которых небезопасно делать структурную копию значений
fd_set
, как показано?
Я обеспокоен, чтобы не было скрытого выделения памяти или чего-то неожиданного. (Существуют макросы / функции FD_SET (), FD_CLR (), FD_ZERO () и FD_ISSET () для маскировки внутренних компонентов приложения.)
Я вижу, что MacOS X (Дарвин) в безопасности; поэтому другие системы на базе BSD, вероятно, будут безопасными. Вы можете помочь, документировав другие системы, которые, как вы знаете, безопасны в ваших ответах.
(У меня есть небольшие опасения по поводу того, насколько хорошо fd_set
будет работать с более чем 8192 дескрипторами открытых файлов - максимальное количество открытых файлов по умолчанию составляет всего 256, но максимальное число «неограниченно». Кроме того, поскольку структуры имеют размер 1 КБ, код копирования ужасно не эффективен, но выполнение списка файловых дескрипторов для воссоздания маски ввода в каждом цикле также не обязательно эффективно. Может быть, вы не можете сделать select()
, когда у вас столько дескрипторы файлов открыты, хотя именно тогда вам, скорее всего, понадобится эта функциональность.)
Есть связанный с этим вопрос - вопрос о 'poll () vs select ()' , который решает другой набор вопросов из этого вопроса.
Обратите внимание, что в MacOS X - и, по-видимому, BSD в более общем смысле - есть макрос или функция FD_COPY()
с эффективным прототипом:
extern void FD_COPY(const restrict fd_set *from, restrict fd_set *to);
.
Возможно, стоит подражать на платформах, где она еще не доступна.