Russian Qt Forum

Qt => Qt Embedded => Тема начата: footballer от Июнь 25, 2007, 06:56



Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: footballer от Июнь 25, 2007, 06:56
Пишу прогу для некой Embedded железяки.
Железяка на АРМ под Линухом. Управление все делается по Serial.
Вывод графики под QT  вносит существенные задержки
и поэтому в основном MessageLoop невозможно реализовать
некий наш протокол. Софтина работает великолепно под QT Win32
Однако под Линухом выплывают траблы...

Пытаюсь написать обработку входящих
пакетов в асинхронном режиме:
Код:

    saio.sa_handler = signal_handler_IO;
    sigaction(SIGIO,&saio,NULL);
    fcntl(m_fd, F_SETOWN, getpid());    
    fcntl(m_fd, F_SETFL, FASYNC);


signal_handler_IO - позволяет вроде реагировать мгновенно на входящие байтики, однако необходимо использовать mutex-ы
для блокировки ввода вывода. Реализовал блокировки на
pthread_mutex_t  (пробовал и QMutex)

Все блоки которые используются
pthread_mutex_lock  -  pthread_mutex_unlock
сделаны на коротких участках кода
причем в одном scope
(на самом деле я использую конструктор - деструктор нотацию
а-ля CSingleLock )
тем не менее софтина попадает все время в залоченное состояние
(deadlocks).
Облазил сорцы в инете, никто ничего загадочного не делает в этом месте

Вопрос к Linux-QT девелоперам:

1.  Объясните PLS какие ограничения при работе с SIGIO
сигналом? Какие подводные камни?

Могу я считать сигнал просто другой ниткой?
Или это та же нитка что и основная?

2. SIGIO может случаться рекурсивно?
(в принципе я это могу проверить
но хотелось бы сначала теорию).

3.  Какие могут возникнуть проблемы с QT очередью?
  или с графикой (у меня Frame Buffer) при работе с pthread_mutex_t

У кого есть  опыт написания подобных вещей?
Поделитесь PLS!


Название: Re: [Qt embedded] Посоветуйте как работать с COM Портом в Li
Отправлено: Steven_Orko от Июнь 25, 2007, 09:03
Цитата: "footballer"

Могу я считать сигнал просто другой ниткой?
Или это та же нитка что и основная?
2. SIGIO может случаться рекурсивно?
(в принципе я это могу проверить
но хотелось бы сначала теорию).


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

Не понял, с каким смыслом здесь употребляется слово "рекурсивно". Обработчик сигнала вызывается сразу, как пришел сигнал... При этом может прерваться выполнявшийся до этого обработчик сигнала...


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: vaprele07 от Июнь 25, 2007, 10:15
http://qextserialport.sourceforge.net/


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: pastor от Июнь 25, 2007, 10:31
Цитата: "vaprele07"
http://qextserialport.sourceforge.net/


footballer нужен асинхроный режим. Насколько я помню qextserialport работает в синхронном


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Tonal от Июнь 25, 2007, 10:41
А может проще вынести всю работу с портом в отдельный поток, а сним уже налаживать коммуникацию?


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: footballer от Июнь 25, 2007, 11:49
Цитата: "Tonal"
А может проще вынести всю работу с портом в отдельный поток, а сним уже налаживать коммуникацию?
Похоже действительно единственный выход.
Просто я надеялся что SIGIO  позволит мне работать в однонитевой модели

Похоже это невозможно.

Просто однонитевость позволяет планировать (хотя это все тоже условно)  что будет происходить в Real Time c задержками. Два
потока мне ничего не гарантируют. И придется уповать на бога.
Ну что ж попробую...


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Tonal от Июнь 25, 2007, 12:18
1) Разве ты не можешь выставить приоритет потока?
2) Т.к. обработчик сигнала выполняется в основной нити, то нет никакой надобности в мутексах. А вот в volatile - есть.
3) Из чего ты заключил, что на сигналах Real Time получиться, а на потоках нет?


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Alex Forth от Июнь 25, 2007, 13:41
Цитата: "footballer"

Просто однонитевость позволяет планировать (хотя это все тоже условно)  что будет происходить в Real Time c задержками. Два
потока мне ничего не гарантируют. И придется уповать на бога.
Ну что ж попробую...

1)Посмотри на политики планирования выполнения процессов/тредов.
2)Если для тебя критично время переключения контекста, то лезь в ядро.


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: footballer от Июнь 26, 2007, 06:53
Спасибо всем.
Как все делать в двунитевой модели мне в общем то понятно
и про приоритеты потоков я думал...
Просто внутри сидит некое предубеждение,
что вторая нить приведет к потере общей производительности.
Проц который я применяю уж больно долго выводит на экран.

( Sharp LH79520 со встроенным контроллером LCD ,
я применил LCD 800x480x16 ) В первоначальной модели все построил на событиях основного Message Loop. В Виндах хватило производительности а на
этом кристалле не хватило.

Теперь завожу вторую нить и в ней пытаюсь отработать все протокольные таймауты.

А вот еще вопрос :

Существует вариант чтения по Serial под Линухом, когда read или select
вываливается, если встретился некий терминирующий байт?


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Alex03 от Июнь 28, 2007, 06:06
Есть мнение что в линухе нет приоритетов потоков....


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Steven_Orko от Июнь 28, 2007, 08:46
2Alex03
Почитайте Процессы и потоки (http://www.citforum.ru/programming/unix/proc_&_threads/), а также Потоки (часть 1) (http://www.citforum.ru/programming/unix/threads/) и Потоки (часть 2) (http://www.citforum.ru/programming/threads_2/).
Приоритеты есть. Я сам их использовал под МСВС. ))))


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Alex03 от Июнь 29, 2007, 08:53
Цитата: "Steven_Orko"
2Alex03
Почитайте Процессы и потоки (http://www.citforum.ru/programming/unix/proc_&_threads/), а также Потоки (часть 1) (http://www.citforum.ru/programming/unix/threads/) и Потоки (часть 2) (http://www.citforum.ru/programming/threads_2/).


Третья ссылки видимо д.б. такая Потоки (часть 2) (http://www.citforum.ru/programming/unix/threads_2/)?
Ну и где по приведённым ссылкам хоть одно упоминание слова "приоритет" или pthread_attr_setinheritsched()?

Цитировать

Приоритеты есть. Я сам их использовал под МСВС. ))))

Что есть МСВС? Российская военная версия линуха?

То что есть вызовы и т.д. я знаю. Но повторю:
Есть мнение (не моё, сам пока не проверял) что в линухе нет приоритетов потоков....

добавлено спустя 45 минут:

 Попробовал, эксперимент подтверждает мои слова.
Посмотрите на вывод примерчика в линуксе и, например, в винде:
Код:
#include <qthread.h>

class MyThread : public QThread
{
    unsigned int m_tId;
    public:
        MyThread(unsigned int tId, unsigned int stackSize = 0);
        virtual void run();
};

MyThread::MyThread(unsigned int tId, unsigned int stackSize) :
          QThread(stackSize)
{
    m_tId = tId;
}

void MyThread::run()
{
    volatile int n, m;
    for(n = 0; n < 20; n++)
    {
        for(m = 0; m < 100000000; m++)
        {
        }
        qWarning( "Thread %u n=%d", m_tId, n);
    }
}

int main()
{
    MyThread t1(1);
    MyThread t2(2);
    MyThread t3(3);
    MyThread t4(4);
    t1.start(QThread::IdlePriority);
    t2.start(QThread::LowestPriority);
    t3.start(QThread::HighestPriority);
    t4.start(QThread::TimeCriticalPriority);

    t1.wait();
    t2.wait();
    t3.wait();
    t4.wait();
}


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Steven_Orko от Июнь 29, 2007, 09:31
хм... Я тут подправил твой тестик. Результаты не очень. Я в самом начале как-то делал тоже самое, запустит пару раз и все. Подумал, что результаты достоверны ((((

Вот тест:
Код:

#include <unistd.h>
#include <qdatetime.h>
#include <qthread.h>
#include <qmutex.h>
#include <qwaitcondition.h>

class MyThread : public QThread
{
public:
    MyThread(unsigned int tId, unsigned int stackSize = 0);
    virtual void run();
   
    static void runAll();
   
private:
    QTime _tm;
    unsigned int m_tId;
};

QMutex g_mutex;
QWaitCondition g_cond;

 
MyThread::MyThread(unsigned int tId, unsigned int stackSize)
: QThread(stackSize)
{
    m_tId = tId;
}
 
void MyThread::run()
{
   
    g_mutex.lock();
    g_cond.wait(&g_mutex);
    g_mutex.unlock();
   
   
    _tm.start();
    volatile long int n, m, t;
    for(n = 0; n < 20; n++)
    {
t = 0;
        for(m = 0; m < 100000000; m++)
        {
   t += 1;
}
    }
    t = _tm.elapsed();
    qWarning("Elapsed  ID%u - %ld", m_tId, t);
}

void MyThread::runAll()
{
    g_mutex.lock();
    g_cond.wakeAll();
    g_mutex.unlock();
}
 
int main()
{
    MyThread t1(1);
    MyThread t2(2);
    MyThread t3(3);
    MyThread t4(4);
    t1.start(QThread::IdlePriority);
    t2.start(QThread::LowestPriority);
    t3.start(QThread::HighestPriority);
    t4.start(QThread::TimeCriticalPriority);
   
    ::sleep(2);
    MyThread::runAll();
 
    t1.wait();
    t2.wait();
    t3.wait();
    t4.wait();
}  


В Линуксе выводит как попало. Иногда все верно, иногда первый поток первым завершался ((((

Цитировать

Elapsed  ID1 - 13335
Elapsed  ID2 - 14011
Elapsed  ID3 - 14105
Elapsed  ID4 - 14167


Так что... я теперь тоже присоединяюсь ко мнению об отсутствие реализации приоритетов потоков в Линуксе... В МСВС (Мобильная система Вооруженных сил) та же фигня, если хотя бы десяток раз тестик прогнать.


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Alex03 от Июнь 29, 2007, 12:31
Мой тест в винде давал такие результаты:
Код:

Thread 4 n=0
Thread 3 n=0
Thread 4 n=1
Thread 3 n=1
Thread 4 n=2
Thread 3 n=2
Thread 4 n=3
Thread 3 n=3
Thread 4 n=4
Thread 3 n=4
Thread 4 n=5
Thread 3 n=5
Thread 4 n=6
Thread 3 n=6
Thread 4 n=7
Thread 3 n=7
Thread 4 n=8
Thread 3 n=8
Thread 4 n=9
Thread 3 n=9
Thread 4 n=10
Thread 3 n=10
Thread 4 n=11
Thread 3 n=11
Thread 4 n=12
Thread 3 n=12
Thread 4 n=13
Thread 3 n=13
Thread 4 n=14
Thread 3 n=14
Thread 4 n=15
Thread 3 n=15
Thread 4 n=16
Thread 3 n=16
Thread 4 n=17
Thread 3 n=17
Thread 4 n=18
Thread 3 n=18
Thread 4 n=19
The thread 'Win32 Thread' (0xa68) has exited with code 0 (0x0).
Thread 3 n=19
The thread 'Win32 Thread' (0xe98) has exited with code 0 (0x0).
Thread 2 n=0
Thread 1 n=0
Thread 2 n=1
Thread 1 n=1
Thread 2 n=2
Thread 1 n=2
Thread 2 n=3
Thread 1 n=3
Thread 2 n=4
Thread 1 n=4
Thread 2 n=5
Thread 1 n=5
Thread 2 n=6
Thread 1 n=6
Thread 2 n=7
Thread 1 n=7
Thread 2 n=8
Thread 1 n=8
Thread 2 n=9
Thread 1 n=9
Thread 2 n=10
Thread 1 n=10
Thread 2 n=11
Thread 1 n=11
Thread 2 n=12
Thread 1 n=12
Thread 2 n=13
Thread 1 n=13
Thread 2 n=14
Thread 1 n=14
Thread 2 n=15
Thread 1 n=15
Thread 2 n=16
Thread 1 n=16
Thread 2 n=17
Thread 1 n=17
Thread 2 n=18
Thread 1 n=18
Thread 2 n=19
The thread 'Win32 Thread' (0x988) has exited with code 0 (0x0).
Thread 1 n=19
The thread 'Win32 Thread' (0xf44) has exited with code 0 (0x0).
The program '[1376] ptest.exe: Native' has exited with code 0 (0x0).


добавлено спустя 26 минут:

 
Цитата: "Steven_Orko"

В Линуксе выводит как попало. Иногда все верно, иногда первый поток первым завершался ((((
Цитировать

Elapsed  ID1 - 13335
Elapsed  ID2 - 14011
Elapsed  ID3 - 14105
Elapsed  ID4 - 14167


Я бы предложил переделать засечку времени на одновременную:
Цитировать

QMutex g_mutex;
QWaitCondition g_cond;
QTime g_tm;

Цитировать

    t = g_tm.elapsed();
    qWarning("Elapsed  ID%u - %ld", m_tId, t);

Цитировать

    ::sleep(2);
    g_tm.start();
    MyThread::runAll();


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: vaprele07 от Июнь 29, 2007, 12:41
приоритет выставляется POSIX функцией pthread_setschedparam


Название: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: Steven_Orko от Июнь 29, 2007, 13:19
Кусок из исходников Qt:
Код:

            sched_param sp;
            sp.sched_priority = prio;

            if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0
                || pthread_attr_setschedpolicy(&attr, sched_policy) != 0
                || pthread_attr_setschedparam(&attr, &sp) != 0) {
                // could not set scheduling hints, fallback to inheriting them
                pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
            }
            break;


Название: Re: [Qt embedded] Посоветуйте как работать с COM Портом в Linux
Отправлено: sja от Январь 24, 2008, 22:30
Я недавнорешал такую же задачу - графика накуте, а данные через компорт - я сделал так: создал отдеьлный поток (тхреад) для компорта (я юзал АПИ для работы с компортом:
int fd = open("/dev/ttyS0", и тд
у меня всё ок, всё справляется и не тормозит на 400мhz машине.