Работа с COM и LPT в Win32. | страница 25



>#include

>. . .

>DCB dcb;

>COMMTIMEOUTS ct;

>HANDLE port;

>DWORD mask;

>DWORD bc;

>char buf[101];

>. . .

>dcb.DCBlength = sizeof(DCB);

>BuildCommDCB("baud=9600 parity=N data=8 stop=1", &dcb);

>dcb.fNull = TRUE;

>ct.ReadIntervalTimeout = 10;

>ct.ReadTotalTimeoutMultiplier = ct.ReadTotalTimeoutConstant = 0;

>ct.WriteTotalTimeoutMultiplier = ct.WriteTotalTimeoutConstant = 0;

>port = CreateFile("COM2", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0 ,NULL);

>SetCommState(port, dcb);

>SetCommTimeouts(port, &ct);

>PurgeComm(port, PURGE_RXCLEAR);

>. . .

>SetCommMask(port, EV_RXCHAR);

>WaitCommEvent(port, &mask, NULL);

>ReadFile(port, buf, 100, &bc, NULL);

>CloseHandle(port);

>. . .

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

Освобождать процессор на время ожидания хорошо, но хотелось бы параллельно с вводом/выводом делать какую-либо полезную работу. Что бы это стало возможным, необходимо в качестве параметра dwFlagsAndAttributes вместо 0 указать FILE_FLAG_OVERLAPPED. Кроме того, для функций ReadFile, WriteFile и WaitCommEvent необходимо в качестве параметра lpOverlapped указывать адрес правильно инициализированной структуры OVERLAPPED. Вот как выглядит эта структура:

>typedef struct _OVERLAPPED {

> DWORD Internal;

> DWORD InternalHigh;

> DWORD Offset;

> DWORD OffsetHigh;

> HANDLE hEvent;

>} OVERLAPPED, *LPOVERLAPPED;

Подробно описывать поля этой структуры не буду, поскольку данная статья не о файловом вводе/выводе вообще, а о работе с портами. Для наших целей, за исключением WaitCommEvent, можно просто обнулить все поля этой структуры. Для WaitCommEvent поле hEvent должно содержать корректный описатель объекта "событие". Что бы все стало понятно, надо разобраться с таким обязательным атрибутом параллельной работы как синхронизация.

ВНИМАНИЕ!!! Дескриптор файла, в данном случае дескриптор файла порта, является синхронизирующим объектом ядра (согласно официальной документации Microsoft). Это означает, что его можно использовать в функциях ожидания событий наравне с дескрипторами событий. Таким образом в поле hEvent в структуре OVERLAPPED можно занести NULL и ожидать освобождения дескриптора файла, а не дескриптора события. Это действительно работает в Windows NT. Однако в Windows95/98 все совсем иначе. Обсуждение ошибок, неточностей и прочих проблем документации оставим в стороне. Просто замечу, что в Windows95/98 поле hEvent должно содержать корректный дескриптор объекта event В ЛЮБОМ СЛУЧАЕ!!! Иначе функции асинхронного ввода/вывода будут работать более чем странным образом. Кроме того, мы должны ожидать освобождения именно дескриптора этого события, а не дескриптора файла.