select (): В чем причина увеличения аргумента nfds на 1? [Дубликат]

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

3
задан Fiddling Bits 2 July 2014 в 20:08
поделиться

4 ответа

Это случайная деталь (оригинальная) реализация сокетов Berkeley. В основном, реализация использовала номер файловых дескрипторов в качестве переменной размера для некоторых временных внутренних битовых массивов. Поскольку дескрипторы Unix начинаются с нуля, наибольший дескриптор будет на один меньше, чем размер любого массива с семантикой с одним слотом на дескриптор. Следовательно, требование «наибольшее-плюс-одно». Эта настройка плюс-1 могла быть поглощена самим системным вызовом, но не была.

Древняя история, вот и все. В результате правильная интерпретация первого аргумента имеет меньшее отношение к значениям дескриптора , чем к числу из них (т. Е. Максимальное количество дескрипторов, подлежащих тестированию). См. Раздел 6.3 из Stevens et al (Это переработанная и обновленная версия классического текста Rich Stevens. Если у вас ее нет, получите ее!) [/ ​​G6]

3
ответ дан arayq2 18 August 2018 в 04:07
поделиться
  • 1
    Это имеет смысл в плюсе 1. Спасибо за ответ и за ссылку. Если я понял ответ Remy Lebeau и ваши внутренние битовые массивы содержат элементы бит, которые активируются при добавлении дескриптора? – mark4rd 2 July 2014 в 21:04
  • 2
    В исходной реализации Berkeley внутренние битовые массивы собираются заново для каждого системного вызова. Во всех вызовах не поддерживается состояние. Рич Стивенс также рассказал о подробностях gory здесь – arayq2 2 July 2014 в 22:14

В большинстве ABI-ядер UNIX аргументы fd_set * для select на самом деле unsigned * или unsigned long *, которые указывают на массивы слов, содержащих биты. Первый аргумент select сообщает ядру, насколько велики эти массивы и сколько бит должно быть проверено.

Каждое слово содержит 16 или 18 или 32 или 36 или 64 бит (в зависимости от словаризации машина); ядро будет читать nfds/wordsize слова из пользовательского пространства, используя nfds%wordsize младшие биты из последних слов (и всех битов других слов).

Структура данных fd_set и связанные с ней функции были введены POSIX, чтобы иметь простой способ управления этими битами, которые также могут быть переносимыми для других систем, которые использовали некоторое другое представление и уровень ядра ABI.

1
ответ дан Chris Dodd 18 August 2018 в 04:07
поделиться

Идея заключается в том, что первый параметр может использоваться функцией выбора для оптимизации времени, считывающего fd_set.

В руководстве:

man select

указано:

nfds - наименованый файловый дескриптор в любом из трех наборов, плюс 1.

Таким образом, функция select проверяет только, что fds меньше этого в fd_set, а не все возможные fds в fd_set. Этот размер определен в константе FD_SETSIZE.

1
ответ дан Cristiano Araujo 18 August 2018 в 04:07
поделиться
  • 1
    Это бессмысленно. fd_set может иметь несколько значений. Если select() "проверяет только fds меньше этого в fd_set и не все возможные fds в fd_set", это будет пропускать значения. – Remy Lebeau 2 July 2014 в 20:21
  • 2
    Предполагается, что @RemyLebeau nfds является файловым дескриптором с наивысшим значением + 1. ie, если вы поместите дескрипторы файлов 5, 9, 90 в fd_set, вы установите аргумент nfd равным 91. Любые дескрипторы файлов, которые вы разместили в fd_set меньше 91 - и ни один из дескрипторов, которые вас интересуют, будет пропущен. – nos 2 July 2014 в 22:10
  • 3
    Я понимаю, что nfd. Посмотрите на формулировку своего ответа, хотя: «функция select проверяет только, что fds меньше этого значения в fd_set , а не все возможные fds в fd_set ». Это означает, что значения, добавленные в fd_set, могут быть пропущены. Просто исправьте свою формулировку, чтобы было ясно, что select() не проверяет все возможные fds, а только fds, фактически добавленные в fd_set. – Remy Lebeau 2 July 2014 в 22:15
  • 4
    Ну, дескрипторы действительно будут пропущены, если вы добавите дескрипторы со значениями & gt; = аргумент nfds, – nos 2 July 2014 в 22:33

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

В Windows сокеты представлены дескрипторами объектов ядра, а не индексами. Структура fd_set содержит массив дескрипторов сокетов и счетчик числа сокетов в массиве. Таким образом, select() может просто перебирать массив, и поэтому первый параметр select() игнорируется в Windows.

5
ответ дан Remy Lebeau 18 August 2018 в 04:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: