LINUX.ORG.RU

чтение несколькими потоками нескольких COM


0

1

Кто-нибудь знает как можно организовать работу следующего приложения на С:
1. Есть несколько COM портов, с которых периодически поступают данные
2. Каждый порт слушается отдельным тредом

Мне надо сделать так, чтоб просыпался только тот тред, который слушает порт, с которого пришли данные.

Я пока пользуюсь sigaction, но в ней не знаю как указать, что надо слушать только определённый порт. Или хотя бы как понять из-за какого порта произошло событие SIGIO ?

Уверен, что должны быть решения такой проблемы, но никак не могу найти

2. Каждый порт слушается отдельным тредом

Т.е. слушающий поток блокируется на read?

Begemoth ★★★★★ ()

А вообще если тебе нужны события от ввода/вывода то epoll тебе в руки и 1 поток на все порты.

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

> А вообще если тебе нужны события от ввода/вывода то epoll тебе в руки

epoll

Накуя? Почувствовать себя крутым Linux-only прогером?

tailgunner ★★★★★ ()

> Я пока пользуюсь sigaction, но в ней не знаю как указать, что надо слушать только определённый порт. Или хотя бы как понять из-за какого порта произошло событие SIGIO ?

man poll

tailgunner ★★★★★ ()

Каждый порт слушается отдельным тредом

read(2) блокируется пока данных нет. Чё не так?

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

read мне не подходит, т.к. каждый пакет должен иметь заголовок и чексумму. И время получения всей последовательности ограничено. Т.е. я использую read с таймаутом. И если не вся последовательность пришла, так и сообщаю на уровень выше.

Проблема в том, что канал не гарантирует доставку всех байтов. Это виртуальный tty интерфейс подключённый через ethernet к конвертору rs232->ethernet

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

>COM'ы - в венде и в досе.

При чём тут линукс?

Ха-ха-ха. По теме сказать нечего?

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

>select + FD_ISSET

А можно пример с использованием select в моём случае? просто данные могут поступать с нескольких портов одновременно

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

read мне не подходит, т.к. каждый пакет должен иметь заголовок и чексумму

е.ь, вот это проблема! и ты себя еще С програмистом называешь? тебе сложно написать ф-ю которая запоминает в статической переменной сколько байтиков пришло? про АКС не читал штоле?

если не вся последовательность пришла, так и сообщаю на уровень выше.

ну правильно, не вижу проблемы. повторяю свой вопрос: что не так? тебе не нравится байтики перекладывать из одного места в другой? так это на С всегда так, инфа 100%. не нравится - п.уй в вебдизигнары.

Проблема в том, что канал не гарантирует доставку всех байтов

проблема в головах. утверждение «что-то там не гарантирует» справедливо для 99% всех вызовов везде. по-этому и были придуманы EXIT_FAILURE и errno & Co. Так что не пори тут чушь. Нету у тебя никакой проблемы. Взял и написал.

read мне не подходит.

б. если тебе read не подходит для того что бы байтики из дескриптора считывать на Ц, то тебе наверняка подойдёт бетономешалка и стамеска. Лопата тоже может подойти. Успехов.

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

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

Нашёл пример в книге «Beginning Linux Programming» Nail Matthew. буду пытаться.

Тут можно посоветовать книгу Стивенса «UNIX Network Programming», он рассматривает обработку событий ввода/вывода.

Begemoth ★★★★★ ()
Ответ на: комментарий от mi_estas

> и ты себя еще С програмистом называешь? тебе сложно написать ф-ю которая запоминает в статической переменной сколько байтиков пришло?

Не знаю, называет ли ТС себя Си-программистом, но ты себя так не называй.

tailgunner ★★★★★ ()
Ответ на: комментарий от Alex007
timeout.tv_sec = 0;
timeout.tv_usec = 300000;

port = new SerialPort("/dev/ttyS0");
fd0 = port->openCom();
if (fd0 == -1)
{
    qDebug("  error while opening port");
}

dummy = new SerialPort("/dev/ttyS1");
fd1 = dummy->openCom();

while (bRun)
{
    FD_ZERO(&rfds);
    FD_SET(fd0, &rfds);
    FD_SET(fd1, &rfds);
    maxfd = MAX(fd0, fd1) + 1;
    int nSelect = select(maxfd, &rfds, 0, 0, &timeout);
    if (nSelect > 0)
    {
        if (FD_ISSET(fd0, &rfds))
        {
            int nRead = port->readData(buffer, 64);
        }
        if (FD_ISSET(fd1, &rdfs))
        {
            // ...
        }
    }
}

Примерно как-то так. Этот код работает в классе-потомке от QThread. Практически копия man select_tut.

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