2013-11-22 2 views
4

Я пытаюсь написать простую программу последовательной связи C для Linux. Я смущен о блокирующих/неблокирующих чтениях и отношениях VMIN/VTIME.termios VMIN VTIME и блокирующие/неблокирующие операции чтения

Мой вопрос в том, должен ли я быть настройками VMIN/VTIME в зависимости от того, есть ли у меня блокирующий/неблокирующий открытый вызов?

Например, если у меня есть следующий открытый вызов:

open("/dev/ttyS0", O_RDWR|O_NONBLOCK|O_NOCTTY) 

Должен ли я установить Vmin/VTIME к:

.c_cc[VTIME] = 0;  
.c_cc[VMIN]  = 0; 

и если я блокирующий режим, как:

open("/dev/ttyS0", O_RDWR|O_NOCTTY) 

Должен ли я установить VMIN/VTIME на:

.c_cc[VTIME] = 0;  
.c_cc[VMIN]  = 1; 

?

Имеет ли значение значение VMIN/VTIME, даже если флаги открытия порта установлены соответствующим образом?

Если кто-нибудь может помочь мне понять взаимосвязь между VMIN/VTIME и блокирующими/неблокирующими портами, я был бы очень признателен.

Благодаря

ответ

-1

Я бы рекомендовал использовать Vmin и VTIME как 0, если вы используете неблокирующее чтение. Это даст вам поведение, которое, если данные доступны, затем будет возвращено; fd будет готов к выбору, опросу и т. д. всякий раз, когда будут доступны данные.

vmin и vtime полезны, если вы делаете блокирующие чтения. Например, если вы ожидаете определенный размер пакета, вы можете установить vmin. Если вы хотите, чтобы вы получали данные каждые полсекунды, вы могли установить vtime.

Очевидно Vmin и VTIME только для неканонического режима (режим без линия)

Я подозреваю, что в неблокируемом режиме, если вы установите Vmin сказать до 5, то FD считываться не будет готовы и read вернет EWOULDBLOCK, пока не будут готовы 5 символов. Я не знаю, и у меня нет простого тестового примера, потому что все серийные работы, которые я сделал, были либо заблокированы, либо установлены как на 0.

2

Андрей прав. В неблокирующем режиме VMIN/VTIME не имеют эффекта (FNDELAY/O_NDELAY, похоже, являются вариантами Linux для O_NONBLOCK, портативного флага POSIX).

При использовании select() с файлом в неблокирующем режиме вы получаете событие для каждого байта, который приходит. При высоких скоростях передачи данных это забивает процессор. Лучше использовать режим блокировки с VMIN, так что select() ждет блока данных перед запуском события, а VTIME - для ограничения задержки для блоков, меньших VMIN.

Сэм сказал: «Если вы хотите убедиться, что вы получаете данные каждые полсекунды, вы можете установить vtime» (VTIME = 5).

Интуитивно, вы можете ожидать, что это правда, но это не так. Эта страница BSD termios объясняет это лучше, чем Linux (хотя оба они работают одинаково). Таймер VTIME является таймером . Он начинается с каждого нового байта, поступающего на последовательный порт. В худшем случае select() может подождать до 20 секунд перед запуском события.

Предположим, что у вас есть VMIN = 250, VTIME = 1 и последовательный порт со скоростью 115200 бит/с. Также предположим, что у вас есть подключенное устройство, медленно отправляющее одиночные байты с постоянной скоростью 9 сП. Время между байтами составляет 0,11 секунды, достаточно долго для истечения интервала таймера от 0.10 и выберите(), чтобы сообщить читаемое событие для каждого байта. Все хорошо.

Теперь предположим, что ваше устройство увеличивает скорость вывода до 11 кадров в секунду. Время между байтами составляет 0,09 секунды. Недостаточно времени для истечения таймера между байтами, и каждый новый байт начинается. Чтобы получить читаемое событие, VMIN = 250 должен быть удовлетворен. При 11 сП, что занимает 22,7 секунды. Может показаться, что ваше устройство остановилось, но дизайн VTIME является реальной причиной задержки.

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

Лучшая конструкция имела бы таймер, закрепленный, а не катящийся. Он будет продолжать тикать, пока он не истечет, или VMIN не будет удовлетворен, в зависимости от того, что наступит раньше. Существующий проект может быть исправлен, но есть 30 лет наследия для преодоления.

На практике вы можете столкнуться с таким сценарием редко. Но он скрывается, так что будьте осторожны.

+0

В статье http://www.cmrr.umn.edu/~strupp/serial.html#config говорится: «Тайм-ауты игнорируются в режиме канонического ввода или когда параметр NDELAY установлен в файл через открытый или fcntl ", а затем он говорит:" VTIME указывает количество времени ожидания входящих символов в десятых долях секунды. Если VTIME установлен в 0 (по умолчанию), чтение будет блокировать (ждать) неопределенно, если параметр NDELAY не установлен порт с открытым или fcntl ». Это означает, что когда VTIME равно 0, вы должны использовать 'O_NDELAY', но когда VTIME> 0, то вы не должны использовать' O_NDELAY'. Это правильно? – CMCDragonkai

Смежные вопросы