| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > boost :: asio реализация proactor и reactor |
| Автор: null56 15.11.2013, 14:06 | ||||
| Добрый день Речь идет о внутренностях библиотеки asio из boost Для начала хотелось бы уточнить терминологию, которая используется в boost, а с ней и паттерн реализациии http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/overview/core/async.html Речь пойдет о асинхронных операциях и их реализациях, на примере чтения из сокета Если судить по картинке, процедура обработки происходит следующим образом: 1) инициатор делает запрос на асинхронное чтение используя интерфейс сокета
2) асинхронный процессор отвечает за исполнение операции чтения и наполнению событиями завершения той или иной операции, помещая их в очередь (completion event queue) 3) оповещением и обработкой завершенных событий занимается проактор 4) запуск проактора (обработчика событий) происходит через вызов
Меня интересует реализация в asio, а именно: 1) когда мы запускаем socket.async_read, что происходит? имеет ли место в данном случае дополнительный поток (асинхронный процессор), который обрабатывает запрос и передает его ОС? далее, скажем, при завершении операции, он формирует сообщение и отправляет его в очередь проактора? а когда мы делаем io_service.run, то уже работаем с цепочкой сформированных событий из нашей нити 2) если первый пункт моего понимания верен, то я хотел бы спросить про реализация в системах, где нет асинхронных слежений (select, epoll, и др), как тогда работает асинхронный процессор? спасибо |
| Автор: null56 15.11.2013, 14:54 | ||||
| bsa, получается так ЗЫ : введу термин: task_manager == io_service async.read добавляет задачу в очередь task_manager, но задача в дейсвительности не будет выполняться, пока не будет вызван run? то есть сказанное ниже неверно (хотя я как раз представлял себе именно так): 1) мы отправили запрос(операцию read), который уже выполняется где - то в фоне 2) спустя время мы захотели узнать не готов ли ответ на запрос и запустили io_service.run
не знал, буду иметь в виду
ну тут доп поток напрашивался... Но не слишком ли расточительно использовать поток на постоянный опрос сокета(ов)? |
| Автор: bsa 15.11.2013, 15:03 | ||
На счет асинхронного чтения я ничего сказать не могу. Не делал такого. У меня все начинается с асинхронного резолва DNS. Поэтому async_read я никогда не делал первой задачей в io_service. В принципе, это и не важно. io_service.run() нужно запускать в начале программы и работать он должен до ее конца. Иначе смысла в азио практически нет. |
| Автор: null56 15.11.2013, 15:28 |
| в общем суть работы ясна, спасибо |
| Автор: mabrarov 15.11.2013, 15:43 | ||||||||||||||||
| To null56 Для начала смотрим в документацию: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/core/basics.html http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/core/async.html
Код Asio запускает асинхронную операцию средствами ОС (тут же, в этом же методе socket::async_read_some) - в случае, если ОС поддерживает такой вид асинхронных операций, в противном случае Asio эмулирует это (socket::async_connect в Windows). Эмуляция обычно происходит путем добавления новой задачи в свой собственный внутренний пул протоков (может состоять из одного потока).
Нет, никаких дополнительных потоков в этом месте не создается (за исключением случаев эмуляции - все они описаны в http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/implementation.html, Threads). Cчитать io_service "асинхронным процессором" несколько неточно/некорректно. Вот что сказано в http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/core/async.html#boost_asio.overview.core.async.proactor_and_boost_asio:
По факту "процессором" выступает сама ОС, ее вызовы встроены в соотв. stream_socket_service и пр. io_service::service. io_service - демультиплексор событий, разгребающий список наступивших событий по мере вызова io_service::run/run_one/poll/poll_one. Видимо, для упрощения (со стороны пользователя Asio) и более тесной интеграции/оптимизации, service-ы, представляющие собой интерфейс для доступа к процессору асинхронных операций встроены в сам io_service.
В общем, да. За исключением того, что в роли проактора выступает сам же io_service.
Да (см. http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/core/async.html#boost_asio.overview.core.async.proactor_and_boost_asio). Только:
Эмулируется (см. выше) за счет синхронных операций и внутренних очередей/пулов потоков (отдельных потоков). To bsa
Разве что в случае эмуляции или же внутри ОС. В других случаях немедленно (в этом же потоке/в этом же методе) стартует асинхронная операция. Это важно - см. нюансы завершения потоков-инициаторов асинхронной операции на сокете и IOCP в Windows.
Не совсем правильно. Опрос (демультиплексирование) происходит в одном (или во всех - как уж позволяет соотв. механизм ОС - IOCP и epoll тут используются по-разному) из потоков, вызывающих io_service::run/run_one/poll/poll_one[/url]: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/implementation.html |
| Автор: null56 15.11.2013, 18:17 | ||||||
вот это, я так себе и представлял, хотя bsa считает, что в этот момент ничего не произойдет, пока не запустим run, а событие чтения будет хранится с проактором (io_service) про эмуляцию потока, я тоже себе это представлял и bsa развеял мои сомнения
до доки я видимо не добрался, а вот io_service я не помню, чтобы называл асинхронным процессором
вот это я хотел, прежде всего, услышать спасибо |
| Автор: mabrarov 15.11.2013, 18:58 | ||||||||
Ну если bsa действительно именно так считает, то он ошибается.
Вообще те внутренние потоки (например, поток для таймера), которые иногда используются, тоже можно вписать в то, что написал bsa. Только они не есть основной метод демультиплексирования - они только для эмуляции, когда по другому не получается/неэффективно (под Windows раньше не было выделенного потока для таймеров - использовался таймаут ожидания на completion port). Основной механизм демультиплексирования/диспетчеризации работает именно в тех потоках, которые вызывают io_service::run/run_one/poll/poll_one.
Там очень много такого, что (почему-то) не лежит на поверхности, но всплывает если прочитать всю (!) доку (включая все примеры).
Пардон, занесло. Вообще заходите на https://github.com/mabrarov/asio_samples и http://asio-samples.blogspot.ru/. Когда-то я хотел заниматься популяризацией Asio. |
| Автор: bsa 15.11.2013, 22:38 |
| Если честно, я не знал, как это работает. В любом случае, я считаю, что данные тонкости новичку знать точно не нужно, иначе запутается. Так как начальное его представление было - сделал async_read, запустил run, он завершился, чтение выполнено. Что мягко говоря несколько неправильно. Это я назвал io_service диспетчером задач. На мой взгляд, для новичков этого знания вполне достаточно. А те, кто ковыряется в потрохах, здесь вопросы подобные не задают. |