Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
чтиво_ч2.doc
Скачиваний:
8
Добавлен:
15.11.2019
Размер:
285 Кб
Скачать
☆

Перекрытый ввод/вывод: блокирование

Первая модель перекрытого ввода/вывода, о которой я расскажу, использует объект события для сигнализирования о завершении. Эта модель во многом похожа на WSAEventSelect, но отличием является то, что объект устанавливается в сигнализированное состояние при завершении WinSock операции, а не при наступлении какого-то сетевого события.

Программа: «Отправь-ка эти данные» WinSock: «Окей, но я не могу отправить их прямо сейчас» Программа ждет сигнала от объекта события, указывающего на то, что функция завершена

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

Перекрытый ввод/вывод: polling

Так же как и в ранее упомянутой модели polling, в этой модели так же можно запросить статус выполнения операции (хотя в ранее описанном polling’e мы не запрашивали статус выполнения, а просто получали данные о неудачном завершении функции. Но основной поток программы знал, когда функция завершилась неудачно, а когда наоборот). С помощью функции WSAGetOverlappedResult можно узнать статус выполняемой операции. Графическая интерпретация перекрытого polling’а очень похожа на интерпретацию обычного polling’а, за исключением того, что WinSock функция выполняется в то же время, что и опрос программы о выполнении функции.

Программа: «Отправь-ка эти данные» WinSock: «Окей, но я не могу отправить их сейчас» Программа: «Уже отправил?» WinSock: «Нет» Программа: «Уже отправил?» WinSock: «Нет» Программа: «Уже отправил?» WinSock: «Нет» Программа: «Уже отправил?» WinSock: «Да! »

И тут я повторюсь: эта модель не очень хороша, так как она приводит процессор в панику. Поэтому я не рекомендую использовать эту модель.

Перекрытый ввод/вывод: процедуры завершения

Процедуры завершения – процедуры обратного вызова (т.е. вызываются в ответ на определенное действие. Далее я буду называть эти процедуры процедурами отзыва), которые вызываются при завершении операции. Тут вроде бы все просто, но есть одна хитрость: эти процедуры вызываются в контексте потока, который начал операцию. Что это значит? Представьте себе поток, который запросил перекрытую операцию записи. WinSock выполняет эту операцию, в то время как Ваш поток тоже выполняется. Таким образом у WinSock есть свой собственный поток для этой операции. Когда операция закончится, WinSock должен вызвать процедуру отзыва. Если это произойдет, то вызванная процедура будет выполняться в контексте потока WinSock. Это означает, что поток, вызвавший операцию записи, будет выполняться одновременно с процедурой вызова. Проблема состоит в том, что синхронизация с вызывающим потоком отсутствует, и он не знает, завершена ли операция (только если ему не сообщат об этом из параллельного потока).

Что бы избежать этого, WinSock удостоверяется в том, что процедура отзыва протекает в том же потоке, из которого происходил запрос. Осуществляется это с помощью APC (Asynchronous Procedure Call или Асинхронный Вызов Процедуры), механизма, встроенного в Windows. Это можно представить как «внедрение» процедуры в основной поток выполнения программы. Таким образом, поток сначала выполнит процедуру, а потом будет делать, то, что делал до ее «внедрения». Естественно, что система не может приказать потоку: «Прекрати делать все, что делал и обработай сначала эту процедуру».

Для того, что бы обеспечить «внедрение» в нужное место механизм APC требует, что бы поток находился в, так называемом, извещающем состоянии ожидания. Каждый поток имеет свою собственную APC очередь, в которой процедуры ждут своего вызова. Когда поток входит в извещающее состояние ожидания, это указывает на то, что он готов обслуживать очередь APC. Перекрытый ввод/вывод с процедурами завершения использует APC для уведомления о завершении операции.

Программа: «Отправь-ка эти данные» WinSock: «Окей, но я не могу отправить их сейчас» Программа входит в извещающее состояние ожидания Функция завершилась Состояние ожидания получает сигнал, о том, что функция завершена Выполняется функция отзыва и управление переходит к программе

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