Создает ли порт завершения ввода-вывода новый поток до или после того, как порт завершения имеет что-то сообщить?

Я немного смущен тем, что на самом деле происходит, когда порт завершения ввода-вывода завершается.

Я предполагаю, что Win API разрешает доступ к очереди IOCP, которая каким-то образом может ставить в очередь (или складывать) ссылку обратного вызова с определенным дескриптором (скажем, сокет). Когда Windows получает прерывание от NIC, тогда оно в какой-то момент попадает в очередь IOCP для NIC и выполняет обратные вызовы в своем собственном (IOCP) пуле потоков.

Мой вопрос: этот поток из пула потоков порожден при получении прерывания, или он на самом деле порожден при вызове Win API, фактически имея поток в состоянии ожидания, пока он не будет разбужен IOCP очередь?

РЕДАКТИРОВАТЬ:
Я нашел это: http://msmvps.com/blogs/luisabreu/archive/2009/06/04/multithreading-io-and-the-thread-pool.aspx где заявляет: «Когда эта операция завершается, он ставит пакет в очередь на этот порт завершения ввода-вывода. Затем порт продолжит работу и будет использовать один из потоков пула потоков для выполнения указанного вами обратного вызова».


person kasperhj    schedule 01.11.2012    source источник
comment
Просто для пояснения, это вопрос о том, как перекрывающийся ввод-вывод управляет приемом уведомлений о событиях до, чтобы передать их в управляемый пользователем пул потоков IOCP, правильно?   -  person WhozCraig    schedule 01.11.2012
comment
Нет. Это вопрос о том, создаются ли потоки, созданные IOCP, до того, как будет произведен некоторый ввод-вывод для порта (в этом случае они заблокированы), или же потоки создаются в то время, когда порт имеет некоторый ввод-вывод, о котором следует сообщить.   -  person kasperhj    schedule 01.11.2012
comment
Не очень понятно, о чем вы говорите. Прерывания обрабатываются драйвером. Имеет значение, использует ли ваш код GetQueuedCompletionStatus () или более позднюю версию CreateThreadPoolIo (). В первом случае вы создаете поток tp. В последнем случае Windows создает его по завершении перекрывающегося ввода-вывода.   -  person Hans Passant    schedule 01.11.2012
comment
@HansPassant Я тоже пытался понять это. Ясно (во всяком случае для меня) он не говорит о пуле потоков, управляемом пользователем (все те потоки, которые вызывают GetQueueCompletionStatus () и регистрируются в состоянии ожидания IOCP). Я почти уверен, что последнее в вашем описании, но вы правы, ясности в этом вопросе не так много   -  person WhozCraig    schedule 01.11.2012
comment
Порты завершения ввода-вывода не создают потоков. Вы создаете потоки и подписываете их на IOCP, когда вызываете GetQueueCompletionStatus.   -  person Raymond Chen    schedule 01.11.2012
comment
На самом деле я лишь косвенно контактирую с IOCP, поскольку использую асинхронные шаблоны C #. Вероятно, поэтому мой вопрос не очень ясен - мои знания по предмету не так хороши. Я уточню завтра.   -  person kasperhj    schedule 02.11.2012
comment
@RaymondChen Значит, мои потоки заблокированы, пока IOCP их не разблокирует?   -  person kasperhj    schedule 02.11.2012
comment
@lejon: если вы вызываете GetQueuedCompletionStatus() с его параметром dwMillisecond, установленным на ненулевое значение, тогда да, вызывающий поток будет заблокирован до завершения IOCP или истечения тайм-аута, в зависимости от того, что произойдет раньше.   -  person Remy Lebeau    schedule 02.11.2012


Ответы (1)


Вероятно, проще представить порт завершения ввода-вывода просто как потокобезопасную очередь, в которую операционная система помещает для вас результаты перекрывающихся операций после их завершения.

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

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

Это более сложно, но вы должны думать именно так.

person Len Holgate    schedule 01.11.2012
comment
Просто для уточнения. В своем приложении я создаю свой собственный пул потоков и передаю поток пула потоков в IOCP, который затем блокируется IOCP, пока что-то не завершится? Это трудно понять, потому что существуют разные мнения о том, как это работает на самом деле, например см. мое редактирование. - person kasperhj; 02.11.2012
comment
Потоки в вашем пуле будут блокироваться IOCP в ожидании работы, все остальное такое же, как указано в моем ответе. То, как пул решает изменить количество потоков, которые он держит, никоим образом не связано с IOCP. Он может отслеживать, когда его потоки вызвали GetQueuedCompletionStatus (), и если ни один из них в настоящее время не имеет и истекает некоторый тайм-аут, он может создать больше потоков, и они затем заблокируются на IOCP, ожидая работы. Я не знаю реализации пула потоков, поэтому больше ничего не могу сказать. - person Len Holgate; 02.11.2012
comment
Предположим, я вызываю IOCP в потоке пользовательского интерфейса, он будет блокироваться, пока я не получу свой пакет IOCP? У вас есть ссылка на внутренности IOCP? - person kasperhj; 05.11.2012
comment
Под вызовом IOCP, я полагаю, вы имеете в виду вызов GetQueuedCompletionStatus () или аналогичный? Если да, то да, он будет блокироваться до тех пор, пока не будет доступен пакет завершения. Нет, у меня нет никаких ссылок на внутреннее устройство IOCP. Я только что прочитал документацию MSDN, книги Рихтера и другие материалы. - person Len Holgate; 05.11.2012
comment
Понятно. Просто кажется странным, что этот факт нигде четко не описан (что мне удалось найти). Буквально сегодня утром я смотрел слайды из выступления Мэдса Торгерсена, и на слайде появились следующие слова: Несколько секунд спустя, и веб-службы доставили свой ответ в ветку порта завершения ввода-вывода! - person kasperhj; 05.11.2012
comment
ИМХО для этого не нужно больше документации. Документация для IOCP в целом хороша, книги Рихтера очень подробны, и если вы прочитали и поняли, как работают собственные API-интерфейсы и последствия их использования, то довольно легко применить эти знания в этой ситуации и рассуждать о том, что происходит ( что полезно приобрести). При желании вы могли бы написать несколько простых тестовых программ, чтобы лучше понять, что происходит на самом деле. - person Len Holgate; 06.11.2012
comment
В документе msdn по .NET я обнаружил следующее: Операции отправки / получения в сокете могут выполняться асинхронно с помощью IOCompletionPort, поэтому, когда наш запрос выполнен, функция обратного вызова SendCallback выполняется в потоке CompletionPort. , ты хоть представляешь, зачем они это пишут? - person kasperhj; 06.11.2012
comment
У вас есть ссылка на то, где вы взяли эту цитату, я хотел бы немного подробнее ... - person Len Holgate; 06.11.2012
comment
Я только что понял, что реализация пула потоков CLR может иметь отдельный пул для IOCP, и это то, что на самом деле блокируется. - person kasperhj; 08.11.2012