Работа с 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 В ЛЮБОМ СЛУЧАЕ!!! Иначе функции асинхронного ввода/вывода будут работать более чем странным образом. Кроме того, мы должны ожидать освобождения именно дескриптора этого события, а не дескриптора файла.