Использование системного вызова select для работы с несколькими каналами
Для простых приложений применение неблокирующих операций чтения и записи работает прекрасно. Для работы с множеством каналов одновременно существует другое решение, которое заключается в использовании системного вызова select.
Представьте ситуацию, когда родительский процесс выступает в качестве серверного процесса и может иметь произвольное число связанных с ним клиентских (дочерних) процессов, как показано на рис. 7.4.
В конечном итоге получится однонаправленный поток данных от дочернего процесса к родительскому. Эта упрощенная ситуация показана на рис. 7.3.
Дочерний процесс 1 |
| Родительский процесс | |||||||
fdwrite() | fdw1 > > | > > fdr1 | fdread() | ||||||
Дочерний процесс 2 | |||||||||
fdwrite() | fdw2 > > | > > fdr2 | fdread() | ||||||
Рис. 7.4. Клиент/сервер с использованием каналов
В этом случае серверный процесс должен как-то справляться с ситуацией, когда одновременно в нескольких каналах может находиться информация, ожидающая обработки. Кроме того, если ни в одном из каналов нет ожидающих данных, то может иметь смысл приостановить работу серверного процесса до их появления, а не опрашивать постоянно каналы. Если информация поступает более чем по одному каналу, то серверный процесс должен знать обо всех таких каналах для того, чтобы работать с ними в правильном порядке (например, согласно их приоритетам).
Это можно сделать при помощи системного вызова
select (существует также аналогичный вызов poll). Системный вызов
select используется не только для каналов, но и для обычных файлов, терминальных устройств, именованных каналов (которые будут рассмотрены в разделе 7.2) и сокетов (им посвящена глава 10). Системный вызов select показывает, какие дескрипторы файлов из заданных наборов готовы для чтения, записи или ожидают обработки ошибок. Иногда серверный процесс не должен совсем прекращать работу, даже если не происходит никаких co6ытий, поэтому в вызове select также можно задать предельное время ожидания.