Использование перекрывающегося именованного канала для одновременного чтения и записи в Windows

У меня есть ручка трубы, которая была создана как перекрытая. Мне нужно читать и записывать в него данные параллельно. Как я могу этого добиться?

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

Как правильно сделать это в C ++ в Windows? Я не могу подать правильный пример или какую-либо помощь по теме.

Основная проблема, с которой я сталкиваюсь, - это обычные блоки ReadFile, когда нет данных для чтения, и в конечном итоге я не могу писать с помощью WriteFile. Я не нашел ни одного метода, который мог бы сказать мне, есть ли что-то, что можно прочитать, что не блокирует. Насколько я понимаю, мне нужно передать структуру OVERLAPPED, но я не знаю, как ее использовать в случае параллельного чтения и записи в один канал (не много).

Это должно быть возможно, как сказано в Синхронный ввод-вывод с перекрытием каналов:

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


person Dmitry Trofimov    schedule 03.08.2013    source источник
comment
Я не нашел ни одного метода, который мог бы сказать мне, есть ли что-то, что нужно прочитать, что не блокирует. - посмотрите _ 1_.   -  person Remy Lebeau    schedule 28.03.2015


Ответы (2)


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

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

Вместо этого представьте, что вы пишете каждую из двух функций с использованием неперекрывающегося ввода-вывода, но всякий раз, когда вы вызываете ReadFile или WriteFile, включайте действительную структуру OVERLAPPED с дескриптором события и выполняйте WaitForSingleObject. Вы должны знать несколько вещей: вы должны убедиться, что каждый поток создает свой собственный объект события, и вы должны обрабатывать случай, когда операция ввода-вывода завершается немедленно (т.е. возвращает ERROR_SUCCESS вместо ERROR_IO_PENDING). В остальном все довольно просто.

Если вы не можете заставить его работать, покажите свой код.

person Harry Johnston    schedule 08.08.2013

Как указано в документации для каналов говорит: один процесс пишет, другой читает. Если вы хотите ПРОЧИТАТЬ и ЗАПИСАТЬ, вам понадобятся два канала: один для «записи в другой процесс», а другой для «чтения данных из другого процесса».

[Это характерно не только для Windows, но, поскольку вы спрашиваете о каналах Windows, я подумал, что лучше предоставить документацию по Windows. Linux / Unix-каналы работают одинаково - у них два конца, конец чтения и написать конец]

Конечно, как говорится в комментарии, документация Windows кажется довольно противоречивой (и я когда-либо использовал каналы Windows только в одном направлении за раз).

Хотя этот пример не читает и не пишет ОДНОВРЕМЕННО, я думаю, что его можно относительно легко изменить, чтобы это было так.

Я подозреваю (но поскольку код не опубликован) проблема либо в вызове ReadFile, либо в настройке самого канала. Перекрывающиеся вызовы ReadFile являются асинхронными, и вам потребуется дождаться события, связанного с перекрывающейся структурой с помощью WaitForMultipleObjects, прежде чем проверять результаты.

Очевидно, что если вы читаете и пишете одновременно, вам нужна одна перекрывающаяся структура для чтения и одна для записи, чтобы указать, какая сторона «завершена».

person Mats Petersson    schedule 03.08.2013
comment
Как Синхронный и перекрывающийся канал I / Документация O гласит: «Перекрывающиеся операции» позволяют одному каналу одновременно читать и записывать данные, а одному потоку выполнять одновременные операции ввода-вывода на нескольких дескрипторах каналов. - person Dmitry Trofimov; 04.08.2013
comment
Хорошо, я изучаю это. - person Mats Petersson; 04.08.2013
comment
@DmitryTrofimov: Как сказано в моей редакции, я думаю, вам нужно показать, что вы делаете (в небольшом, полном, компилируемом примере, если это вообще возможно). - person Mats Petersson; 04.08.2013
comment
Вот почему я задал вопрос: как можно легко изменить пример для работы с одним конвейером? Когда мне нужно писать, читать и ждать? Каких событий мне ждать? - person Dmitry Trofimov; 04.08.2013
comment
Вам нужна (как минимум) одна перекрывающаяся структура с событием в каждой для чтения и записи. Вы вызываете ReadFile, чтобы установить триггер для некоторых данных, поступающих с другой стороны. Когда у вас есть данные для записи, вы вызываете WriteFile. Если вы вызвали ReadFile или WriteFile, вы не должны вызывать ни то, ни другое, пока не сработает соответствующее событие. Есть несколько десятков различных способов добиться этого, и что правильно или неправильно, зависит от того, что вы на самом деле пытаетесь сделать. - person Mats Petersson; 04.08.2013
comment
В одной ветке прочитал все доступные данные. В другом я пишу, есть ли у меня данные для записи. То, что я не понимаю, что я должен проверить перед вызовом WriteFile, чтобы убедиться, что он не читает сейчас, и что проверить, чтобы убедиться, что он не пишет. И что и когда мне нужно подождать :) - person Dmitry Trofimov; 04.08.2013
comment
Насколько я понимаю, вы должны иметь возможность одновременно читать и писать - другими словами, не должно быть проблем с одновременной записью в канал и чтением. Итак, в вашем потоке, который читает, после того, как вы выдадите ReadFile, дождитесь события перекрытия чтения, а поток записи дождитесь четности в перекрывающейся структуре записи. - person Mats Petersson; 04.08.2013
comment
Трубы (в Windows) однозначно могут быть дуплексными. Я без проблем использовал дуплексные каналы с перекрывающимся вводом-выводом, хотя я не читал и не писал одновременно. - person Harry Johnston; 08.08.2013
comment
@DmitryTrofimov, сейчас я занимаюсь этой проблемой и заметил статью, в которой говорится, что перекрывающиеся операции позволяют одному каналу одновременно читать и записывать данные. Пример, на который он указывает, - это машина состояний последовательного чтения / записи, которая не совсем параллельна. - person bvj; 29.03.2015