Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> boost :: asio реализация proactor и reactor, детали реализации 
V
    Опции темы
null56
Дата 15.11.2013, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



Добрый день

Речь идет о внутренностях библиотеки asio из boost

Для начала хотелось бы уточнить терминологию, которая используется в boost, а с ней и паттерн реализациии

http://www.boost.org/doc/libs/1_54_0/doc/h...core/async.html

Речь пойдет о асинхронных операциях и их реализациях, на примере чтения из сокета

Если судить по картинке, процедура обработки происходит следующим образом:

1) инициатор делает запрос на асинхронное чтение используя интерфейс сокета 
Код

boost::asio::ip::tcp::socket socket(io_service);

socket.async_read()


2) асинхронный процессор отвечает за исполнение  операции чтения и наполнению событиями завершения той или иной операции, помещая их в очередь (completion event queue)

3) оповещением и обработкой завершенных событий занимается проактор

4) запуск проактора (обработчика событий) происходит через вызов 
Код

 io_service::run()


Меня интересует реализация в asio, а именно:
1) когда мы запускаем socket.async_read, что происходит? имеет ли место в данном случае дополнительный поток (асинхронный процессор), который обрабатывает запрос и передает его ОС? далее, скажем, при завершении операции, он формирует сообщение и отправляет его в очередь проактора? а когда мы делаем io_service.run, то уже работаем с цепочкой сформированных событий из нашей нити

2) если первый пункт моего понимания верен, то я хотел бы спросить про реализация в системах, где нет асинхронных слежений (select, epoll, и др), как тогда работает асинхронный процессор?

спасибо

PM MAIL   Вверх
bsa
Дата 15.11.2013, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Мне лично не нравится название io_service. Так как оно путает. По факту, это task_manager. Это обработчик очереди заданий. Твоя задача, наполнять эту очередь.

Цитата(null56 @  15.11.2013,  15:06 Найти цитируемый пост)
когда мы запускаем socket.async_read, что происходит? 
происходит постановка задачи "асинхронное чтение из сокета" в очередь
Цитата(null56 @  15.11.2013,  15:06 Найти цитируемый пост)
имеет ли место в данном случае дополнительный поток (асинхронный процессор), который обрабатывает запрос и передает его ОС?
нет
Цитата(null56 @  15.11.2013,  15:06 Найти цитируемый пост)
далее, скажем, при завершении операции, он формирует сообщение и отправляет его в очередь проактора?
типа того. Я бы назвал это не сообщением, а "задачей" (task). И не отправлением, а добавлением.
Цитата(null56 @  15.11.2013,  15:06 Найти цитируемый пост)
а когда мы делаем io_service.run, то уже работаем с цепочкой сформированных событий из нашей нити
Смысл такой. Перед тем, как запустить run у io_service ты должен хоть что-нибудь положить в его очередь. Когда его очередь опустошается, то метод run() завершает работу. Стандартная практика работы с азио заключается в постоянном добавлении задач в очередь из хэндлеров. Например, ты получаешь данные через сокет. запускаешь async_read(), когда приходит порция данных вызывается хэндлер, в котором ты их обрабатываешь и опять запускаешь async_read с тем же хэндлером (в большинстве случаев)... Что-то типа рекурсии (но не рекурсия!).
Цитата(null56 @  15.11.2013,  15:06 Найти цитируемый пост)
если первый пункт моего понимания верен, то я хотел бы спросить про реализация в системах, где нет асинхронных слежений (select, epoll, и др), как тогда работает асинхронный процессор?
Через постоянный опрос состояний в отдельном потоке. Которые генерирует события для потока обработчика.

PM   Вверх
null56
Дата 15.11.2013, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



bsa, получается так

ЗЫ : введу термин: task_manager == io_service

async.read добавляет задачу в очередь task_manager, но задача в дейсвительности не будет выполняться, пока не будет вызван run?

то есть сказанное ниже неверно (хотя я как раз представлял себе именно так):
1) мы отправили запрос(операцию read), который уже выполняется где - то в фоне 
2) спустя время мы захотели узнать не готов ли ответ на запрос и запустили io_service.run

Цитата(bsa @  15.11.2013,  14:36 Найти цитируемый пост)
Смысл такой. Перед тем, как запустить run у io_service ты должен хоть что-нибудь положить в его очередь. Когда его очередь опустошается, то метод run() завершает работу. 

не знал, буду иметь в виду

Цитата(bsa @  15.11.2013,  14:36 Найти цитируемый пост)
Через постоянный опрос состояний в отдельном потоке. Которые генерирует события для потока обработчика.

ну тут доп поток напрашивался... Но не слишком ли расточительно использовать поток на постоянный опрос сокета(ов)?

Это сообщение отредактировал(а) null56 - 15.11.2013, 14:54
PM MAIL   Вверх
bsa
Дата 15.11.2013, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(null56 @  15.11.2013,  15:54 Найти цитируемый пост)
Но не слишком ли расточительно использовать поток на постоянный опрос сокета(ов)?
Там один поток на все асинхронные операции может использоваться.

Цитата(null56 @  15.11.2013,  15:54 Найти цитируемый пост)
async.read добавляет задачу в очередь task_manager, но задача в дейсвительности не будет выполняться, пока не будет вызван run?
На счет асинхронного чтения я ничего сказать не могу. Не делал такого. У меня все начинается с асинхронного резолва DNS. Поэтому async_read я никогда не делал первой задачей в io_service. В принципе, это и не важно. io_service.run() нужно запускать в начале программы и работать он должен до ее конца. Иначе смысла в азио практически нет.
PM   Вверх
null56
Дата 15.11.2013, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



в общем суть работы ясна, спасибо
PM MAIL   Вверх
mabrarov
Дата 15.11.2013, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

Репутация: 8
Всего: 9



To null56
Для начала смотрим в документацию:
http://www.boost.org/doc/libs/1_55_0/doc/h...ore/basics.html
http://www.boost.org/doc/libs/1_55_0/doc/h...core/async.html

Цитата
когда мы запускаем socket.async_read, что происходит?

Код Asio запускает асинхронную операцию средствами ОС (тут же, в этом же методе socket::async_read_some) - в случае, если ОС поддерживает такой вид асинхронных операций, в противном случае Asio эмулирует это (socket::async_connect в Windows). Эмуляция обычно происходит путем добавления новой задачи в свой собственный внутренний пул протоков (может состоять из одного потока).

Цитата
имеет ли место в данном случае дополнительный поток (асинхронный процессор), который обрабатывает запрос и передает его ОС?

Нет, никаких дополнительных потоков в этом месте не создается (за исключением случаев эмуляции - все они описаны в http://www.boost.org/doc/libs/1_55_0/doc/h...ementation.html, Threads). Cчитать io_service "асинхронным процессором" несколько неточно/некорректно.
Вот что сказано в документации
Цитата
Asynchronous Operation Processor
Executes asynchronous operations and queues events on a completion event queue when operations complete. From a high-level point of view, services like stream_socket_service are asynchronous operation processors.

По факту "процессором" выступает сама ОС, ее вызовы встроены в соотв. stream_socket_service и пр. io_service::service. io_service - демультиплексор событий, разгребающий список наступивших событий по мере вызова io_service::run/run_one/poll/poll_one. Видимо, для упрощения (со стороны пользователя Asio) и более тесной интеграции/оптимизации, service-ы, представляющие собой интерфейс для доступа к процессору асинхронных операций встроены в сам io_service.

Цитата
далее, скажем, при завершении операции, он формирует сообщение и отправляет его в очередь проактора?

В общем, да. За исключением того, что в роли проактора выступает сам же io_service.

Цитата
а когда мы делаем io_service.run, то уже работаем с цепочкой сформированных событий из нашей нити

Да (см. Asynchronous Event Demultiplexer). Только:
  • цепочка событий может наполняться еще и за счет io_service::post/dispatch, а не только за счет завершения асинхронных операций.
  • на самом деле это не цепочка (не очередь), а предоставляемый ОС механизм демультиплексирования завершенных асинхронных операций (IOCP, epoll, dev/poll, kqueue, select). Вот уже внутри этого механизма ОС может быть и очередь (IOCP - встроенный в ядро ОС проактор).
  • кроме механизма демультиплексирования ОС там же может использоваться внутренняя очередь (очереди). Например, так сделано в Asio на Windows (кроме IOCP есть еще отдельная внутренняя очередь для io_service::post/dispatch, которая используется, если IOCP не может быть использован/выдал ошибку/для оптимизации).
  • для таймеров иногда (не скажу про все платформы, но на Windows - точно начиная с какой-то версии Boost.Asio, сделано для оптимизации) так же используется отдельный внутренний поток, который ждет наступления таймаута (по отсортированному списку таймаутов) и при наступлении таймаута посылает событие в демультиплексор (возможно, средствами ОС) - вот вам простой пример эмуляции асинхронной операции ожидания.

Цитата
то я хотел бы спросить про реализация в системах, где нет асинхронных слежений (select, epoll, и др), как тогда работает асинхронный процессор?

Эмулируется (см. выше) за счет синхронных операций и внутренних очередей/пулов потоков (отдельных потоков).

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/h...ementation.html
PM MAIL WWW Skype   Вверх
null56
Дата 15.11.2013, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



Цитата(mabrarov @  15.11.2013,  15:43 Найти цитируемый пост)
Код Asio запускает асинхронную операцию средствами ОС (тут же, в этом же методе socket::async_read_some) - в случае, если ОС поддерживает такой вид асинхронных операций, в противном случае Asio эмулирует это (socket::async_connect в Windows). Эмуляция обычно происходит путем добавления новой задачи в свой собственный внутренний пул протоков (может состоять из одного потока).


вот это, я так себе и представлял, хотя bsa считает, что в этот момент ничего не произойдет, пока не запустим run, а событие чтения будет хранится с проактором (io_service)

про эмуляцию потока, я тоже себе это представлял и bsa развеял мои сомнения



Цитата(mabrarov @  15.11.2013,  15:43 Найти цитируемый пост)
Нет, никаких дополнительных потоков в этом месте не создается (за исключением случаев эмуляции - все они описаны в http://www.boost.org/doc/libs/1_55_0/doc/h...ementation.html, Threads). Cчитать io_service "асинхронным процессором" несколько неточно/некорректно.

до доки я видимо не добрался, а вот io_service я не помню, чтобы называл асинхронным процессором smile


Цитата(mabrarov @  15.11.2013,  15:43 Найти цитируемый пост)

Эмулируется (см. выше) за счет синхронных операций и внутренних очередей/пулов потоков (отдельных потоков).

вот это я хотел, прежде всего, услышать


спасибо

PM MAIL   Вверх
mabrarov
Дата 15.11.2013, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

Репутация: 8
Всего: 9



Цитата(null56 @ 15.11.2013,  18:17)
хотя bsa считает, что в этот момент ничего не произойдет, пока не запустим run, а событие чтения будет хранится с проактором (io_service)

Ну если bsa действительно именно так считает, то он ошибается.

Цитата(null56 @ 15.11.2013,  18:17)
про эмуляцию потока, я тоже себе это представлял и bsa развеял мои сомнения

Вообще те внутренние потоки (например, поток для таймера), которые иногда используются, тоже можно вписать в то, что написал bsa. Только они не есть основной метод демультиплексирования - они только для эмуляции, когда по другому не получается/неэффективно (под Windows раньше не было выделенного потока для таймеров - использовался таймаут ожидания на completion port). Основной механизм демультиплексирования/диспетчеризации работает именно в тех потоках, которые вызывают io_service::run/run_one/poll/poll_one.

Цитата(null56 @ 15.11.2013,  18:17)
до доки я видимо не добрался

Там очень много такого, что (почему-то) не лежит на поверхности, но всплывает если прочитать всю (!) доку (включая все примеры).

Цитата(null56 @ 15.11.2013,  18:17)
а вот io_service я не помню, чтобы называл асинхронным процессором

Пардон, занесло.

Вообще заходите на https://github.com/mabrarov/asio_samples и http://asio-samples.blogspot.ru/. Когда-то я хотел заниматься популяризацией Asio.

Это сообщение отредактировал(а) mabrarov - 15.11.2013, 19:00
PM MAIL WWW Skype   Вверх
bsa
Дата 15.11.2013, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(mabrarov @  15.11.2013,  19:58 Найти цитируемый пост)
Ну если bsa действительно именно так считает, то он ошибается.
Если честно, я не знал, как это работает. В любом случае, я считаю, что данные тонкости новичку знать точно не нужно, иначе запутается. Так как начальное его представление было - сделал async_read, запустил run, он завершился, чтение выполнено. Что мягко говоря несколько неправильно.

Это я назвал io_service диспетчером задач. На мой взгляд, для новичков этого знания вполне достаточно. А те, кто ковыряется в потрохах, здесь вопросы подобные не задают.  smile 
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0882 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.