Драйвер Windows NDIS: параллельное чтение/запись на одном устройстве (IRP_MJ_READ/WRITE)

Начиная с образца ndisprot от Microsoft, я пытаюсь написать драйвер протокола NDIS. Из пользовательского пространства я пытаюсь читать и писать на устройство одновременно (из двух потоков). Поскольку я не получаю никаких пакетов, системный вызов ReadFile блокируется. Я не могу выполнить системный вызов WriteFile в этом состоянии.

CHAR            NdisProtDevice[] = "\\\\.\\\\NDISprot";
CHAR *          pNdisProtDevice = &NdisProtDevice[0];

this.iHandle = CreateFile(pNdisProtDevice,
            GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

// Blocks, because no frames arrive

bSuccess = (BOOLEAN)ReadFile(Handle,
                             (LPVOID)pReadBuf,
                             PacketLength,
                             &BytesRead,
                             NULL);

...
// Called some seconds later from another thread, while ReadFile still blocking...
bSuccess = (BOOLEAN)WriteFile(Handle,
                              pWriteBuf,
                              PacketLength,
                              &BytesWritten,
                              NULL); 

Я добавил несколько отладочных сообщений и обнаружил, что функция драйвера, связанная с IRP_MJ_WRITE (NdisprotWrite), даже не вызывается! Что-то между приложением пространства пользователя и драйвером блокирует одновременный доступ к устройству \Device\NDISprot.

Как я могу одновременно читать и писать в файл?


person falstaff    schedule 17.05.2013    source источник
comment
Если ReadFile вызывается только через несколько секунд после WriteFile, как он может отвечать за блокировку записи?   -  person Harry Johnston    schedule 20.05.2013
comment
Потому что ReadFile все еще блокируется... Как только я отправляю пакет на эту машину, ReadFile завершается успешно, и WriteFile немедленно выполняется...   -  person falstaff    schedule 21.05.2013
comment
Улучшенный комментарий к коду   -  person falstaff    schedule 21.05.2013
comment
У меня есть несколько интересных выводов: функция NdisprotRead (которая связана с IRP_MJ_READ) возвращает STATUS_PENDING. IoCompleteRequest, который завершает этот запрос ввода-вывода, выполняется позже, когда поступает новый сетевой фрейм. Остается вопрос: как использовать системный вызов WriteFile, когда драйвер находится в состоянии Pending? Есть ли способ сделать файл доступным для чтения и записи синхронно? Или мне нужно добавить еще один файл (например, один для чтения, один для записи)?   -  person falstaff    schedule 21.05.2013
comment
Ваш код теперь говорит, что ReadFile вызывается, пока ReadFile все еще блокируется. Вы делаете два вызова ReadFile? Каков реальный порядок событий? Вы пытались открыть две ручки, одну для чтения и одну для записи?   -  person Harry Johnston    schedule 21.05.2013
comment
Извините, я перепутал вызовы ReadFile/WriteFile... Сначала я делаю ReadFile, который блокируется, а затем вызов WriteFile не работает. Спасибо за подсказку с использованием двух ручек, не подумал об этом. Я собираюсь попробовать это.   -  person falstaff    schedule 23.05.2013
comment
Спасибо, трюк с двумя ручками работает. Первоначально это не работало, поскольку драйвер разрешал привязку только одного дескриптора к определенному интерфейсу. Но мне пришлось изменить драйвер, чтобы в любом случае можно было подключить несколько клиентов. Итак, теперь каждый клиент подключается дважды, один раз для чтения и один раз для записи...   -  person falstaff    schedule 23.05.2013


Ответы (1)


По умолчанию у вас может быть только один невыполненный запрос ввода-вывода на дескриптор пользовательского режима. Либо откройте несколько дескрипторов, либо откройте один дескриптор с помощью FILE_FLAG_OVERLAPPED. (После того как вы используете FILE_FLAG_OVERLAPPED, вам, как правило, также необходимо использовать структуры OVERLAPPED — убедитесь, что вы уловили суть, просмотрев это и это.)

person Jeffrey Tippet    schedule 23.05.2013
comment
Спасибо за Ваш ответ. Использование нескольких дескрипторов отлично работает для меня (см. также комментарии выше). - person falstaff; 23.05.2013