Как работает функция select () в C ++ в ОС Unix? - PullRequest
1 голос
/ 01 октября 2010

Я использовал функцию select() для реализации серверов, но теперь я должен реализовать ее самостоятельно (как часть проекта).

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

Может кто-нибудь помочь мне реализовать эту функцию? Любые источники, статьи? Кто-нибудь может объяснить, что происходит в этой функции?

Ответы [ 3 ]

3 голосов
/ 01 октября 2010

select - примитив операционной системы. Он не может быть реализован с использованием других переносимых конструкций, таких как pthreads.

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

Итак, pthread_cond_wait не является действительно примитивным с точки зрения реализации; это разработано, чтобы быть очень безопасным семантически. Это дух pthreads, к лучшему или к худшему. Атомарные переменные, доступные в различных библиотеках, предоставляют небезопасную альтернативу реализации примитивов pthreads для заданий синхронизации, но сигнализация включает планирование и отмену планирования потоков, что довольно специфично для платформы. (Ну, если подумать, я думаю, вы могли бы реализовать select с помощью спин-блокировки. Я содрогаюсь от этой мысли.)

Это прекрасное упражнение, чтобы попробовать, хотя.

0 голосов
/ 01 октября 2010

Если вы используете select, то, вероятно, вы (или ваши коллеги) внедряете значительную часть интерфейса ОС. Таким образом, это зависит от того, как вы реализуете подсистему ввода-вывода и планировщик.

Если вы не реализуете планировщик, вам нужен какой-то «центр управления», который использует примитивы синхронизации (возможно, переменные условия) для отслеживания изменений в состояниях дескрипторов файлов, которые вас интересуют.

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

Если вы не реализуете подсистему ввода / вывода, тогда единственный способ реализовать select - это использовать какой-то другой, похожий на примитив, который поддерживает ваша подсистема ввода / вывода. В качестве альтернативы возьмите на себя задачу реализации ввода / вывода: оберните все в своем собственном слое и сделайте select доступным только через этот слой. Реализация этого уровня зависит от базового API, но если все остальное терпит неудачу, вы можете создать один поток на дескриптор файла, заблокировать операции ввода-вывода в этом потоке, а затем уведомить свой «центр управления», когда файл доступен для чтения и записи. , или есть ошибки.

Сначала правильно разработайте дизайн, что, вероятно, означает изучение того, как это делают другие ОС. В противном случае вы будете тратить следующие 2 года на исправление условий гонки.

0 голосов
/ 01 октября 2010

Вы всегда можете взглянуть на реализации с открытым исходным кодом для вдохновения и / или теории работы.

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

Это, конечно, оченьхотя это высокоуровневое описание, которое просто затушевывает многие из множества деталей, которые вам необходимо охватить, чтобы понять это правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...