QextSerialPort::read() и таймаут в Виндоус

При использовании библиотеки QextSerialPort версии 1.2rc в Виндоус возникает проблема медленного чтения данных. Дело в том, что данные, даже если они доступны, возвращаются только после истечения таймаута.

Проблема решается, если открывать порт в режиме QIODevice::Unbuffered, например:

port->open( QIODevice::ReadWrite | QIODevice::Unbuffered );

Такое решение нашлось на Stack Overflow.

Но после этого в моей программе стало некорректно работать чтение в Юникс. Читалось меньше данных, чем запрашивалось, даже при достаточно большом таймауте, как-будто таймаут вообще не работает. Проблема решилась использованием разных режимов на разных операционных системах:

const QIODevice::OpenMode openMode =
#if   (defined Q_OS_UNIX)
    QIODevice::ReadWrite;
#elif (defined Q_OS_WIN)
    QIODevice::ReadWrite | QIODevice::Unbuffered;
#else
    #error "Unknown Operating System"
    QIODevice::NotOpen;
#endif

port->open(openMode);

Мне кажется, первая проблема связана с поведением функции «qint64 QIODevice::read(char *data, qint64 maxSize)» из библиотеки Qt. Проблемная часть кода из файла qiodevice.cpp библиотеки Qt версии 5.3.0:

qint64 QIODevice::read(char *data, qint64 maxSize)
{
    ...
            if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) {
                ...
                int bytesToBuffer = QIODEVICE_BUFFERSIZE;
                ...
                qint64 readFromDevice = readData(writePointer, bytesToBuffer);
                ...
            }
    ...
}

При этом QIODEVICE_BUFFERSIZE задается равным 16384 в файле qiodevice_p.h:

#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)

Функция readData() реализуется в библиотеке QextSerialPort и в Виндоус вызывает функцию ReadFile() из WinApi, которая читает заданное количество байт из COM-порта.

Таким образом, если устройство не открыто в режиме Unbuffered, то в Виндоус у COM-порта запрашивается 16384 байт, чтобы заполнить некий буфер. Если нам требуется меньше данных, то ReadFile() не возвращает управление пока не истечет таймаут.

Автор

Дмитрий Бравиков

Инженер. Электронщик. Программист.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.