Какова цель первого аргумента для выбора системного вызова?


25

От man select

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

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

Какова цель nfds, когда у нас уже есть readfds, writefdsи exceptfdsиз которого могут быть определены файловые дескрипторы?


Я собирался спросить о SO, но здесь она более централизована, и вызовы C API рассматриваются по теме .
phunehehe

Ответы:


25

В статье «Расширенное программирование в среде UNIX» Ричард Стивенс говорит, что это оптимизация производительности:

Указав самый высокий дескриптор, который нас интересует, ядро ​​может избежать прохождения сотен неиспользуемых битов в трех наборах дескрипторов, ища биты, которые включены.

(1-е издание, стр. 399)

Если вы занимаетесь программированием любых систем UNIX, настоятельно рекомендуется книга APUE.


ОБНОВИТЬ

fd_set, Как правило , в состоянии отслеживать до 1024 дескрипторов файлов.

Наиболее эффективный способ отследить, какие из fdsних установлены, 0а какие установлены, - это набор битов 1, поэтому каждый из них fd_setбудет состоять из 1024 битов.

В 32-битной системе long int (или «слово») составляет 32 бита, так что каждый из них fd_setравен
1024/32 = 32 слова.

Если nfdsесть что-то маленькое, например, 8 или 16, которое было бы во многих приложениях, ему нужно только заглянуть внутрь 1-го слова, которое должно быть явно быстрее, чем заглянуть внутрь всех 32.

(См FD_SETSIZEи __NFDBITSс /usr/include/sys/select.hдля значений на вашей платформе.)


ОБНОВЛЕНИЕ 2

Относительно того, почему подпись функции не

int select(fd_set *readfds, int nreadfds,
           fd_set *writefds, int nwritefds,
           fd_set *exceptfds, int nexceptfds,
           struct timeval *timeout);

Я думаю, это потому, что код пытается сохранить все аргументы в регистрах , чтобы ЦПУ мог работать с ними быстрее, и если бы ему пришлось отслеживать дополнительные 2 переменные, ЦП может не иметь достаточно регистров.

Другими словами, selectраскрывает детали реализации, чтобы они могли быть быстрее.


2
Это или более поздний Интерфейс Программирования Linux
Крис

APUE тоже недавно обновился. Второе издание: amazon.com/gp/aw/d.html/ref=aw_d_detail?pd=1&a=0201433079
Микель,

@chris Я проверю интерфейс программирования Linux. Спасибо.
Микель

Спасибо за информацию, я проверю книги, когда захочу.
phunehehe

APUE 2nd Ed: 27 июня 2005 г. (охватывает linux-2.4.22) TLPI: октябрь 2010 г. (охватывает linux-2.6.35)
Крис

6

Я не знаю наверняка, так как я не один из разработчиков select (), но я бы сказал, что это оптимизация производительности. Вызывающая функция знает, сколько файловых дескрипторов она поместила в чтение, запись и, кроме FD, так почему же ядро ​​должно это выяснить снова?

Помните, что в начале 80-х годов, когда появилась функция select (), у них не было мульти-гигагерцевых мультипроцессоров для работы. VAX с частотой 25 МГц был довольно быстрым. Кроме того, вы хотели, чтобы select () работал быстро, если мог: если какой-то ввод-вывод ожидал процесса, зачем заставлять процесс ждать?


На ваш аргумент я бы сказал, что нам нужно nreadfds, nwritefdsа nexceptfdsне только один nfds.
phunehehe

Может быть, это так, что nfdsможно зайти в реестр для более быстрого доступа. Если бы ему нужно было отслеживать три числа вместе со всеми остальными аргументами, возможно, у ЦПУ не было бы достаточно регистров. Конечно, ядро ​​могло бы создать свое собственное nfdsна основе ваших гипотетических 3 переменных. Поэтому я предполагаю, что он раскрывает детали реализации для повышения эффективности.
Микель

@Mikel, phunehehe: отдельные nfdsаргументы приносят очень мало пользы. В большинстве случаев процесс открыл очень мало процессов относительно FD_SETSIZE. Типичный случай может иметь (4,4,2) из ​​1024; проверка ядра (4,4,4) - это большая победа (1024,1024,1024), но оптимизация до (4,4,2) была бы практически бесполезной.
Жиль "ТАК - прекрати быть злым"

@ Жиль: выигрыш будет более чистым API. (На самом деле, либо программист должен выполнить дополнительную работу для вычисления nfds, либо быть ленивым и вызывать select(FD_SETSIZE, ...), что будет медленнее.)
Mikel

OTOH, отслеживание только одной переменной max также может быть проще для программиста.
Микель
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.