На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> SetCommTimeouts
    Никак не могу настроить таймауты.
    В документации сказано
    Цитата

    Если прикладная программа устанавливает члены структуры ReadIntervalTimeout и ReadTotalTimeoutMultiplier в MAXDWORD, а член стуктуры ReadTotalTimeoutConstant
    устанавливается в значение больше чем нуль и меньше, чем MAXDWORD, когда вызывается функция ReadFile, происходит одно из ниже перечисленного:
    1. Если есть какие-либо символы в буфере ввода данных, ReadFile немедленно возвращает значение с символами в буфере.
    2. Если в буфере ввода данных нет никаких символов, ReadFile ждет до тех пор, пока не поступит символ, а затем немедленно возвращает значение.
    3. Если в пределах времени, заданного членом ReadTotalTimeoutConstant, никакого символа не поступает, ReadFile прерывает работу.


    То есть если есть хоть какие-то данные, то управление возвращается сразу.
    У меня ReadIntervalTimeout = ReadTotalTimeoutMultiplier = MAXDWORD, а ReadTotalTimeoutConstant = 1000

    Так вот если в процессе ожидания приходят данные, то управление возвращается не сразу, а выжидается ReadTotalTimeoutConstant.
    В результате чего резко падает скорость.

    Почему так ? Может еще что задать нужно помимо таймаутов ?

    З.Ы. Мне нужно сразу получать данные. Есть все задать нулями, то тогда будет синхронное чтение всего запрашиваемого буфера.
    А мне нужно получать то, что есть.
      У тебя несколько противоречивые желания. Сам подумай: если ничего нет, то подождать 1000 мс; если есть, то вернуть имеющееся без ожидания. Внимание вопрос: что делать, если ничего нет, но через 200 мс пришёл один символ? Вернуть этот самый один, который "всё что есть", или ждать дальше, мол, а вдруг счас ещё парочка набежит?
        Цитата Qraizer @
        У тебя несколько противоречивые желания. Сам подумай: если ничего нет, то подождать 1000 мс; если есть, то вернуть имеющееся без ожидания. Внимание вопрос: что делать, если ничего нет, но через 200 мс пришёл один символ? Вернуть этот самый один, который "всё что есть", или ждать дальше, мол, а вдруг счас ещё парочка набежит?

        ну если пришел один, то придут и следующие. такой протокол

        Решил проблему ассинхронным чтением с ожиданием EV_RXCHAR.
        Жду когда придет хоть один а потом читаю все что есть.
        В результате получается чтение блоками различной длины.

        Но хотелось бы все-таки разобраться с таймаутами...
          Цитата
          Если прикладная программа устанавливает...
          Цитата
          Так вот если в процессе ожидания приходят данные, то управление возвращается не сразу, а выжидается ReadTotalTimeoutConstant.

          Скорее всего, этот текст следует читать как "мы ПЛАНИРОВАЛИ, что функция работать будет вот так, но потом сделали немного иначе". :yes:

          Цитата

          Никак не могу настроить таймауты.
          З.Ы. Мне нужно сразу получать данные.
          Решил проблему ассинхронным чтением с ожиданием EV_RXCHAR.
          Но хотелось бы все-таки разобраться с таймаутами...

          Информации о протоколе обмена с устройством недостаточно. Если устройство передаёт данные, когда ему вздумается, а не в ответ на запрос - асинхронное чтение с ожиданием EV_RXCHAR хороший вариант.
          Сообщение отредактировано: Prince -
            Цитата gpepsi @
            Но хотелось бы все-таки разобраться с таймаутами...
            Конкретно в своей ситуации: функция вернёт всё что есть на момент её вызова, если очередь непуста; в противном случае будет безусловно ждать в течении ReadTotalTimeoutConstant, а затем завершится в любом случае, вернув по окончании ожидания "всё что есть", т.е. в частном случае ничего.
            Сообщение отредактировано: Qraizer -
              Цитата Qraizer @
              онкретно в своей ситуации: функция вернёт всё что есть на момент её вызова, если очередь непуста; в противном случае будет ждать в течении ReadTotalTimeoutConstant, то завершается в любом случае, вернув "всё что есть", т.е. в частном случае ничего.

              не понял. Это при каких настройках ?
                Тебе можно ждать одного символа без таймаута, и если он-таки есть, дочитывать остальное, если же нет, самому выждать 1000 мс, оформив это ожидание как самому удобнее.

                Добавлено
                Цитата gpepsi @
                Это при каких настройках ?
                ReadIntervalTimeout = ReadTotalTimeoutMultiplier = MAXDWORD, а ReadTotalTimeoutConstant = 1000

                Добавлено
                Prince, ты прав. Когда я писал нечто подобное для Win9x, то асинхронность в итоге пришлось делать руками. Управление таймаутами в виде отдельных параметров порта и специальной функции их установки в контенсте асинхронного обмена произвольного рамера сообщениями неудобны, гораздо удобнее управлять ими при каждом вызове ReadFile(). Я тогда написал свою функцию CommReadFile() и управлял логикой задержек изунтри неё посредством Sleep(). Наверное они там подумали, что иметь аж пять дополнительных параметров для функции чтения - причём требовалась уже не ReadFile(), там параметры размещать уже негде - это ещё больший маразм, а скорости COMов таковы, что оверхед железа перекрывает оверхед от частых SetCommTimeouts().

                P.S. Несмотря на уверения, что OVERLAPPED под Win9X для COM реализовано, оно не работало. Или работало не так, как описано, и я не понял, как именно.

                Добавлено
                Кстати, gpepsi, а настройки самого порта каковы? Я имею в виду GetCommProperties(). Тормозить исполнение может ещё и драйвер, не отдавая в юзермод данные, пока их не накопится.
                Сообщение отредактировано: Qraizer -
                  Цитата
                  Prince, ты прав. Когда я писал нечто подобное для Win9x, то асинхронность в итоге пришлось делать руками. Управление таймаутами в виде отдельных параметров порта и специальной функции их установки в контенсте асинхронного обмена произвольного рамера сообщениями неудобны, гораздо удобнее управлять ими при каждом вызове ReadFile().

                  Прав в чём? Я имел в виду синхронный режим. "Нормально", что readfile ожидает ReadTotalTimeoutConstant при ReadIntervalTimeout = ReadTotalTimeoutMultiplier = MAXDWORD - так она и работает, а инфа из справки, видимо, отражает первоначальные планы разработчиков. Вот почему не исправят: или реализацию функции, или описание - загадка. :unsure:
                  О неудобствах таймаутов "в принципе" - не могу судить. Зависит от протокола обмена с девайсом.
                  Сообщение отредактировано: Prince -
                    Цитата Qraizer @
                    Я имею в виду GetCommProperties

                    не вызывал

                    Добавлено
                    Цитата Prince @
                    а инфа из справки, видимо, отражает первоначальные планы разработчиков. Вот почему не исправят, или реализацию функции или описание - загадка.

                    пока я это понял - просидел под PortMon-ом 3 дня :(
                      Цитата Prince @
                      Прав в чём?
                      Вот это:
                      Цитата Prince @
                      этот текст следует читать как "мы ПЛАНИРОВАЛИ, что функция работать будет вот так, но потом сделали немного иначе".
                        Цитата gpepsi @
                        Так вот если в процессе ожидания приходят данные, то управление возвращается не сразу, а выжидается ReadTotalTimeoutConstant.
                        В результате чего резко падает скорость.

                        Попробуй поставить 10 [мс].
                        Кроме того, всё ещё сложнее.
                        Результаты приёма зависят от заданного размера FIFO UART-а.

                        Если мне не изменяет память, в случае когда количество полученных
                        байт меньше, чем размер FIFO UART, то принять их можно только по тайм-ауту.
                          Цитата
                          когда количество полученных байт меньше, чем размер FIFO UART, то принять их можно только по тайм-ауту

                          Это как это? :wacko: Переведи... :wacko: Допустим, размер FIFO UART - килобайт, а нужно принять 1 байт, и этот байт уже принят и лежит в буфере, что означает в данном случае "принять по таймауту"?
                            Ну, килобайт - это ты загнул. Как я понимаю, это вот это:
                            Прикреплённая картинка
                            Прикреплённая картинка
                              Килобайт - для ровного счёта, неважно. Вот что означает "можно принять только по таймауту"? :unsure:
                              Сообщение отредактировано: Prince -
                                Скрытый текст

                                Следующей важной управляющей структурой является COMMTIMEOUTS. Она определяет параметры временных задержек при приеме и передаче. Значения, задаваемые полями этой структуры, оказывают большое влияние на работу функций чтения/записи.





                                typedef struct _COMMTIMEOUTS {
                                DWORD ReadIntervalTimeout;
                                DWORD ReadTotalTimeoutMultiplier;
                                DWORD ReadTotalTimeoutConstant;
                                DWORD WriteTotalTimeoutMultiplier;
                                DWORD WriteTotalTimeoutConstant;
                                } COMMTIMEOUTS,*LPCOMMTIMEOUTS;




                                Поля структуры COMMTIMEOUTS имеют следующие значения:
                                ReadIntervalTimeout

                                Максимальное время, в миллисекундах, допустимое между двумя последовательными символами считываемыми с коммуникационной линии. Во время операции чтения временной период начинает отсчитываться с момента приема первого символа. Если интервал между двумя последовательными символами превысит заданое значение, операция чтения завершается и все данные, накопленые в буфере, передаются в программу. Нулевое значение данного поля означает, что данный тайм-аут не используется. Значение MAXDWORD, вместе с нулевыми значениями полей ReadTotalTimeoutConstant и ReadTotalTimeoutMultiplier, означает немедленный возврат из операции чтения с передачей уже принятого символа, даже если ни одного символа не было получено из линии.

                                ReadTotalTimeoutMultiplier

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

                                ReadTotalTimeoutConstant

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

                                WriteTotalTimeoutMultiplier

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

                                WriteTotalTimeoutConstant

                                Задает константу, в миллисекундах, используемую для вычисления общего тайм-аута операции записи. Для каждой операции записи данное значение прибавляется к результату умножения WriteTotalTimeoutMultiplier на количество записываемых символов. Нулевое значение полей WriteTotalTimeoutMultiplier и WriteTotalTimeoutConstant означает, что общий тайм-аут для операции записи не используется.
                                По тайм-аутам обычно возникает много вопросов. Поэтому попробую объяснить подробнее. Пусть мы считываем 50 символов из порта со скоростью 9600. При этом используется 8 бит на символ, дополнение до четности и один стоповый бит. Таким образом на один символ в физической линии приходится 11 бит (включая стартовый бит). 50 символов на скорости 9600 будут приниматься 50 * 11 / 9600 = 0.0572916 секунд, или примерно 57.3 миллисекунды, при условии нулевого интервала между приемом последовательных символов. Если интервал между символами составляет примерно половину времени передачи одного символа, т.е. 0.5 миллисекунд, то время приема будет 50 * 11 / 9600 + 49 * 0.0005 = 0.0817916 секунд, или примерно 82 миллисекунды. Если в процессе чтения прошло более 82 миллисекунд, то мы вправе предположить, что произошла ошибка в работе внешнего устройства и прекратить считывание избежав тем самым зависания программы. Это и есть общий тайм-аут операции чтения. Аналогично существует и общий там-аут операции записи.
                                Если тайм-аут при чтении понятен, то тайм-аут при записи вызывает недоумение. В самом деле, что нам мешает передавать? Управление потоком! Внешнее устройство может использовать, например, аппаратное управление потоком. При этом пропадание питания во внешнем устройстве заставит компьютер приостановить передачу данных. Если не контролировать тайм-аут возможно точно такое же зависание компьютера, как и при операции чтения.
                                Общий тайм-аут зависит от количества участвующих в операции чтения/записи символов и среднего времени передачи одного символа с учетом межсимвольного интервала. Если символов много, например 1000, то на общем времени выполнения операции начинают сказываться колебания времени затрачиваемого на один символ или времени межсимвольного интервала. Поэтому тайм-ауты в структуре COMMTIMEOUTS задаются двумя величинами. Таким образом формула для вычисления общего тайм-аута операции, например чтения, выглядит так NumOfChar * ReadTotalTimeoutMultiplier + ReadTotalTimeoutConstant, где NumOfChar это число символов запрошеных для операции чтения.
                                Для операции чтения, кроме общего тайм-аута на всю операцию, задается так же тайм-аут на интервал между двумя последовательными символами. Точнее это интервал между началами двух последовательных символов. В это значение входит и время передачи самого символа.
                                Теперь небольшой пример. ReadTotalTimeoutMultiplier = 2, ReadTotalTimeoutConstant = 1, ReadIntervalTimeout = 1, считывается 250 символов. Если операция чтения завершится за 250 * 2 + 1 = 501 миллисекунду, то будет считано все сообщение. Если операция чтения не завершится за 501 миллисекунду, то она все равно будет завершена. При этом будут возвращены символы, прием которых завершился до истечения тайм-аута операции. Остальные символы могут быть получены следеющей операцией чтения. Если между началами двух последовательных символов пройдет более 1 миллисекунды, то операция чтения так же будет завершена.
                                Надеюсь, что теперь тайм-ауты не будут вызывать у Вас затруднений. Для завершения темы тайм-аутов рассмотрим один частный случай. Если поля ReadIntervalTimeout и ReadTotalTimeoutMultiplier установлены в MAXDWORD, а ReadTotalTimeoutConstant больше нуля и меньше MAXDWORD, то выполнение оперции чтения подчиняется следующим правилам:
                                Если в буфере есть символы, то чтение немедленно завершается и возвращается символ из буфера;
                                Если в буфере нет символов, то операция чтения будет ожидать появления любого символа, после чего она немедленно завершится;
                                Если в течении времени, заданого полем ReadTotalTimeoutConstant, не будет принято ни одного символа, оперция чтения завершится по тайм-ауту.
                                Помните функцию BuildCommDCB? Существует еще функция BuildCommDCBAndTimeouts, которая позволяет заполнить не только структуру DCB, но и структуру COMMTIMEOUTS.


                                http://www.realcoding.net/article/view/2416
                                Сообщение отредактировано: Dem_max -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1159 ]   [ 18 queries used ]   [ Generated: 7.04.26, 19:17 GMT ]