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()
, когда у вас есть много дескрипторы файлов открываются, хотя именно тогда вам, скорее всего, понадобятся функции.)
Есть связанный с этим вопрос SO - вопрос о 'poll() vs select()', в котором рассматривается другой набор проблем из этого вопроса.
Обратите внимание, что на MacOS X - и, предположительно, BSD в целом - есть макрос или функция FD_COPY()
с эффективным прототипом:
-
extern void FD_COPY(const restrict fd_set *from, restrict fd_set *to);
.
Возможно, стоит подражать на платформах, где он еще не доступен.