LINUX.ORG.RU

задержка при чтении с COM порта


0

0

открываю СОМ порт в неблокируещем режиме. в бесконечном цикле читаю из него байты. все вроде бы ок. но процессор грузится очень сильно. попытался вставить задержку с помощью функции usleep. но тогда начинают
"пропадать" некоторые байты. задержку ставил от 1 до 1000 микросекунд.
какие будут идеи?

Иван.

anonymous

да вроде без селекта разобрался уже. спасибо.

anonymous
()

поделись, пожалуйста, ....

anonymous
()

ИМХО, селект тут как раз к месту. Просто сам с такой же проблемой сталкивался.

SnakePAN
()

сделал не через select.
нечто вроде этого.

for (;;)
{
n=read(fd,&char,1);
if (n <=0)
{
usleep(100);
}
if (n>0)
{
do somthing :)
}
}

единственно - задержка зависит от скорости работы порта.

anonymous
()

А в чем смысл спать (usleep) в такой конструкции? Чем это принципиально отличается от блокирующего read?

Murr ★★
()

Задержка

Обратите внимание на
if(read() <= 0)
а также на "процессор грузится очень сильно".
Порт, скорее всего, так сконфигурирован... c_cc[VMIN] обнулен,
иначе говоря. Выставить его в 1, забыть про usleep и наслаждаться
селектом.

vnp
()
Ответ на: комментарий от anonymous


Примерно так:

int fd = open(...)
struct termios attr;
tcgetattr(fd, &attr);
attr.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
attr.c_lflag &= ~ICANON | ~ISIG;
attr.c_cc[VMIN] = 1;
tcsetattr(fd, TCSANOW, &attr);
tcflush(fd, TCIFLUSH);
...
fd_set rdset;
while(1) {
FD_SET(fd, &rdset);
select(fd + 1, &rdset, 0, 0, 0);
read(fd, ...);
}

Это с точностью до проверок на ошибки. c_cflag выставляются по надобности; в c_lflag бит ICANON гасить обязательно (иначе получим line buffering и прочие прелести канонического режима, да и VMIN проигнорируется).
Если нужен таймаут, его можно задать в самом select, или же через attr.c_cc[VTIME] (последнее, IMHO, правильнее).

PS: если у Вас только один дескриптор, то select, строго говоря, не нужен; никакой разницы между select/read и просто read не будет. Он становится полезен когда надо читать несколько потоков вперемежку. Для облегчения жизни процессора (с чего все и началось) важна только конфигурация порта.

vnp
()

спасибо за пример с select. мне нужно с несколькоми COM портами одновременно работать. и сейчас думаю как лучше сделать. или через селект их все прогонять или на каждый порт создавать отдельный поток который будет с ним работать (в этом случае получается что селект не нужен(?)). кто что может посоветовать. пока я склоняюсь ко второму варианту.

anonymous
()

А нафиг там select то вообще сдался? :))
Чем это от read будет отличаться?

Завести несколько нитей и будет всё шоколадно ...

Murr ★★
()

дык вот просто попробовал и так и так вроде пашет :) щас решаю как лучше сделать :)

anonymous
()
Ответ на: комментарий от anonymous

Код с несколькими нитями проще в своей "читающей" части, но может оказаться сложнее в координации нитей и данных(не считая накладных расходов на переключение; ими часто можно пренебречь). Код с select, как правило, выглядит уродливо... но прямолинеен как палка. Как всегда, все зависит от конкретной задачи.

vnp
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.