demon051
Помогающий
Offline
|
|
« : 21-02-2018 06:49 » |
|
Всем привет. начал разбираться с таймерами и обнаружил что нет подключаемого файла timer.h
#include <linux/timer.h>
Вроде бы файл, относящийся к ядру системы, а его нет...
Не установлен какой-то пакет? Или что не так?
Debian GNU/Linux 9.3
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #1 : 21-02-2018 07:45 » |
|
А такой файл должен быть? Если Вам нужны POSIX-таймера, которые timer_*(), то они живут в <time.h>.
|
|
|
Записан
|
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #3 : 21-02-2018 09:14 » |
|
Возможно у Вас не установлен пакет linux-headers-4.9.0 с заголовочными файлами ядра. Вы хотите работать с ядерными таймерами в прикладной программе или в модуле ядра?
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #4 : 21-02-2018 09:15 » |
|
Возможно у Вас не установлен пакет linux-headers-4.9.0 с заголовочными файлами ядра. Вы хотите работать с ядерными таймерами в прикладной программе или в модуле ядра?
хотелось бы в прикладной.... это возможно?
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #5 : 21-02-2018 09:36 » |
|
для прикладной есть POSIX-таймера. Ядерные, насколько я знаю, доступны только для модулей ядра/драйверов.
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #6 : 21-02-2018 09:42 » |
|
для прикладной есть POSIX-таймера. Ядерные, насколько я знаю, доступны только для модулей ядра/драйверов.
Я уже смотрю POSIX На мой взгляд - это просто ужас какой-то!!!! Привык я к удобствам винды...
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #7 : 21-02-2018 09:53 » |
|
На мой взгляд - это просто ужас какой-то!!!! Привык я к удобствам винды...
На вкус и цвет все фломастеры разные (с). Как по мне - вполне себе нормальный интерфейс. Создал таймер, настроил его на необходимый сигнал, а дальше либо в обработчике сигнала что-то делаешь, или, если нужно тактирование, ожидаешь нужного сигнала. А можно вообще, правда уже linux-specific, можно сигнал преобразовать в файловый дескриптор и ожидать на стандартном select()/poll(). В общем, насколько я помню windows-таймера, в POSIX функциональность выше, а в Linux - ещё выше..
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #8 : 21-02-2018 10:45 » |
|
На мой взгляд - это просто ужас какой-то!!!! Привык я к удобствам винды...
На вкус и цвет все фломастеры разные (с). Как по мне - вполне себе нормальный интерфейс. Создал таймер, настроил его на необходимый сигнал, а дальше либо в обработчике сигнала что-то делаешь, или, если нужно тактирование, ожидаешь нужного сигнала. А можно вообще, правда уже linux-specific, можно сигнал преобразовать в файловый дескриптор и ожидать на стандартном select()/poll(). В общем, насколько я помню windows-таймера, в POSIX функциональность выше, а в Linux - ещё выше.. Тогда объясните что тут не так #include <unistd.h> #include <stdio.h> #include <time.h> #include <string.h> #include <signal.h>
#define MAX_EXPIRE 10
int expire;
void timer_handler(int signo, siginfo_t *info,
void *context);
int main(){
struct timespec ts, tm, sleep;
sigset_t mask;
siginfo_t info;
struct sigevent sigev;
struct sigaction sa;
struct itimerspec ival;
timer_t tid;
clock_getres(CLOCK_MONOTONIC, &ts);
clock_gettime(CLOCK_MONOTONIC, &tm);
printf("CLOCK_MONOTONIC res: [%d]sec [%d]nsec/n", ts.tv_sec, ts.tv_nsec);
printf("system up time: [%d]sec [%d]nsec\n", tm.tv_sec, tm.tv_nsec);
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = timer_handler;
if (sigaction(SIGRTMIN, &sa, NULL) == -1) {
perror("sigaction failed");
return -1;
}
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = SIGRTMIN;
sigev.sigev_value.sival_int = 1;
if (timer_create(CLOCK_MONOTONIC, &sigev, &tid) == -1){
perror("timer_create");
return -1;
}
printf("timer-id = %d\n", tid);
ival.it_value.tv_sec = 5;
ival.it_value.tv_nsec = 0;
ival.it_interval.tv_sec = 4;
ival.it_interval.tv_nsec = 0;
if (timer_settime(tid, 0, &ival, NULL) == -1){
perror("timer_settime");
return -1;
}
/* Спим и ждём сигнал */
for(;;){
sleep.tv_sec = 3;
sleep.tv_nsec = 0;
printf("sleep...\n");
clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, NULL);
printf("woken up\n");
if (expire >= MAX_EXPIRE){
printf("Program quitting.\n");
memset(&ival, 0, sizeof (ival));
timer_settime(tid, 0, &ival, NULL);
return 0;
}
}
return 0; }
void timer_handler(int signo, siginfo_t *info,
void *context)
{
int overrun;
printf("signal details: signo: (%d), signal (%d), code (%d)\n", signo, info->si_signo, info->si_code);
if (info->si_code == SI_TIMER){
printf("timer-id = %d \n", info->_sifields._timer.si_tid);
expire++;
timer_t *tidp; int orr;
tidp = (void**)&info->si_value.sival_ptr;
printf(" sival_ptr = %p; ", info->si_value.sival_ptr); printf(" *sival_ptr = 0x%lx\n", (long) *tidp);
/*overrun = timer_getoverrun(*tidp);
if (overrun >=0 ) { printf("timer overrun %d\n", overrun);
expire += overrun;
}*/
}
}
после вызова timer_create получаю цифровой идентификатор таймера. в хендлере таймера при попытке получить идентификатор info->_sifields._timer.si_tid всегда равен нулю. в хендлере закомментирован вызов overrun = timer_getoverrun(*tidp); ибо при этом программа стабильно выдает segmentation fault код не я придумал. это когда примера. который повсюду на всех форумах постоянно тиражируется....
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #9 : 21-02-2018 11:13 » |
|
А Вам нужен этот timer_getoverrun()? как вариант - попробуйте сказать не sigev.sigev_value.sival_int = 1; а sigev.sigev_value.sival_ptr = &tid; ну и дальше, поменять: tidp = (void**)&info->si_value.sival_ptr; на tidp = (timer_t*)info->si_value.sival_ptr; PS: для linux в info есть нестандартное поле si_overrun, которое избавляет от вызова timer_getoverrun(), единственный минус - код будет привязан к linux, для работы на других unix-ах надо будет что-то делать дополнительно.
|
|
« Последнее редактирование: 21-02-2018 11:30 от darkelf »
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #10 : 21-02-2018 12:02 » |
|
А Вам нужен этот timer_getoverrun()? как вариант - попробуйте сказать не sigev.sigev_value.sival_int = 1; а sigev.sigev_value.sival_ptr = &tid; ну и дальше, поменять: tidp = (void**)&info->si_value.sival_ptr; на tidp = (timer_t*)info->si_value.sival_ptr; PS: для linux в info есть нестандартное поле si_overrun, которое избавляет от вызова timer_getoverrun(), единственный минус - код будет привязан к linux, для работы на других unix-ах надо будет что-то делать дополнительно. всё так же осталось. segmentation fault но хуже всего - что id попадает нулевой. т.е. как установить от какого таймера событие, если их несколько на одном обработчике?
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #11 : 21-02-2018 12:19 » |
|
странно, у меня - не падает: #include <unistd.h> #include <stdio.h> #include <time.h> #include <string.h> #include <signal.h>
#define MAX_EXPIRE 10
int expire;
void timer_handler(int signo, siginfo_t *info, void *context);
int main(){ struct timespec ts, tm, sleep; sigset_t mask; siginfo_t info; struct sigevent sigev; struct sigaction sa; struct itimerspec ival; timer_t tid;
clock_getres(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &tm);
printf("CLOCK_MONOTONIC res: [%d]sec [%d]nsec/n", ts.tv_sec, ts.tv_nsec); printf("system up time: [%d]sec [%d]nsec\n", tm.tv_sec, tm.tv_nsec);
sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, NULL);
sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = timer_handler;
if (sigaction(SIGRTMIN, &sa, NULL) == -1) { perror("sigaction failed"); return -1; }
sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = SIGRTMIN; sigev.sigev_value.sival_ptr = &tid;
if (timer_create(CLOCK_MONOTONIC, &sigev, &tid) == -1){ perror("timer_create"); return -1; }
printf("timer-id = %d (%lp)\n", tid, &tid);
ival.it_value.tv_sec = 5; ival.it_value.tv_nsec = 0; ival.it_interval.tv_sec = 4; ival.it_interval.tv_nsec = 0;
if (timer_settime(tid, 0, &ival, NULL) == -1){ perror("timer_settime"); return -1; }
/* Спим и ждём сигнал */
for(;;){ sleep.tv_sec = 3; sleep.tv_nsec = 0;
printf("sleep...\n");
clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, NULL);
printf("woken up\n");
if (expire >= MAX_EXPIRE){ printf("Program quitting.\n"); memset(&ival, 0, sizeof (ival)); timer_settime(tid, 0, &ival, NULL); return 0; } }
return 0; }
void timer_handler(int signo, siginfo_t *info, void *context) { int overrun;
printf("signal details: signo: (%d), signal (%d), code (%d)\n", signo, info->si_signo, info->si_code);
if (info->si_code == SI_TIMER){ printf("timer-id = %d \n", info->_sifields._timer.si_tid); expire++;
timer_t *tidp; int orr;
tidp = (timer_t*)info->si_value.sival_ptr;
printf(" sival_ptr = %p (%d); ", tidp, *tidp); printf(" *sival_ptr = 0x%lx\n", tidp);
overrun = timer_getoverrun(*tidp);
if (overrun >=0 ) { printf("timer overrun %d\n", overrun); expire += overrun; } } } По поводу различения таймеров - можно их развесить на разные сигналы, соответственно различать по signo. UPD: поправил пример, добавил распечатку адреса и значения идентификатора таймера - у меня идентификатор таймера нормально передаётся.
|
|
« Последнее редактирование: 21-02-2018 12:39 от darkelf »
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #12 : 21-02-2018 13:14 » |
|
т.е вы хотите сказать, что printf("timer-id = %d \n", info->_sifields._timer.si_tid); у вас выводит адекватный идентификатор? у меня всегда 0 и ещё интересный момент, я например устанавливаю sigev.sigev_value.sival_int = 22; перед созданием таймера а в обработчике printf("sival_int = %d \n", info->_sifields._timer.si_sigval.sival_int ); выводит совсем другое значение... в общем путаница какая-то получается....
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #13 : 21-02-2018 13:55 » |
|
у меня выводит так: root@odroid_22_33:~/de/timer# ./a.out CLOCK_MONOTONIC res: [0]sec [1]nsec/nsystem up time: [6452]sec [735342206]nsec timer-id = 140304 (0xbeb2d44c) sleep... woken up sleep... signal details: signo: (34), signal (34), code (-2) timer-id = 0 sival_ptr = 0xbeb2d44c (140304); *sival_ptr = 0xbeb2d44c timer overrun 0 woken up sleep... woken up sleep... signal details: signo: (34), signal (34), code (-2) timer-id = 0 sival_ptr = 0xbeb2d44c (140304); *sival_ptr = 0xbeb2d44c timer overrun 0 woken up sleep... woken up sleep... signal details: signo: (34), signal (34), code (-2) timer-id = 0 sival_ptr = 0xbeb2d44c (140304); *sival_ptr = 0xbeb2d44c timer overrun 0 woken up sleep... woken up sleep... signal details: signo: (34), signal (34), code (-2) timer-id = 0 sival_ptr = 0xbeb2d44c (140304); *sival_ptr = 0xbeb2d44c timer overrun 0 woken up sleep... woken up sleep... ^C
Обратите внимание на адрес 0xbeb2d44c tid-а и его значение 140304 - они одинаковые как в main()-е, так и в обработчике. кто такой info->_sifields._timer.si_sigval.sival_int я не знаю (но да, у меня здесь тоже выводится 0), но имя с подчёркиванием в начале не добавляет оптимизма, так-что, имхо, лучше на него не смотреть. Передаю идентификатор таймера через info->si_value.sival_ptr.
|
|
« Последнее редактирование: 21-02-2018 14:42 от darkelf »
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #14 : 22-02-2018 05:05 » |
|
Это я понял, спасибо. разница была в том, что я присваивал sigev.sigev_value.sival_ptr = &tid; после вызова timer_create(CLOCK_MONOTONIC, &sigev, &tid) в этом случае в обрабочик указатель не попадал, но зато срабатывало присвоение sigev.sigev_value.sival_int = 1; и в обрабочик эта 1-ца передавалась. если сделать присвоение sigev.sigev_value.sival_ptr = &tid; после timer_create - всё наоборот. указатель попадает, 1-ца - нет. в общем путаница. понятно что можно не обращать внимание но! судя по всему предполагается что с помощью .sival_int = ххх можно в обработчик передавать какой-либо параметр. а он не передается в общем печалька. ну да ладно. еще раз спасибо. я ща задам наверное совсем глупый вопрос. мне приходится писать код для плк на базе процессора imx6 ul имею в качестве среды разработки виртуальную машину с убунтой и Qt, настроенный на соответствующий тулчейн с компилятором под этот проц. так вот... как бы это правильно сказать... в таком разрезе я имею голый с или с++. т.е. исчезли все возможности приятного программирования под Qt c использованием наследования от QObject, сигналов и слотов и прочих плюшек. Виртуалку в данном виде мне передали разработчики ПЛК. Вот я и думаю, а имеется ли возможность всё настроить так, чтобы были и Qbject и сигналы и т.д. Или я обречен на унылую работу с лопатой и ломом? К сожалению до разработчиков железки не достучаться. Они ушли в глухой аут. Типа нате и отбибитесь.... И вот приходится ковыряться со всем этим в одиночку. Ни с ПЛК ни с голым линуксом я до того дела не имел...
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #15 : 22-02-2018 07:54 » |
|
разница была в том, что я присваивал
sigev.sigev_value.sival_ptr = &tid;
после вызова
timer_create(CLOCK_MONOTONIC, &sigev, &tid)
в этом случае в обрабочик указатель не попадал, но зато срабатывало присвоение
sigev.sigev_value.sival_int = 1;
и в обрабочик эта 1-ца передавалась.
Там нельзя одновременно использовать и sival_int и sival_ptr, т.к. sigev_value это union. Попробуйте собрать подправленный мною код - там всё должно работать нормально. мне приходится писать код для плк на базе процессора imx6 ul имею в качестве среды разработки виртуальную машину с убунтой и Qt, настроенный на соответствующий тулчейн с компилятором под этот проц. так вот... как бы это правильно сказать... в таком разрезе я имею голый с или с++. т.е. исчезли все возможности приятного программирования под Qt c использованием наследования от QObject, сигналов и слотов и прочих плюшек. Виртуалку в данном виде мне передали разработчики ПЛК. Вот я и думаю, а имеется ли возможность всё настроить так, чтобы были и Qbject и сигналы и т.д. Или я обречен на унылую работу с лопатой и ломом? К сожалению до разработчиков железки не достучаться. Они ушли в глухой аут. Типа нате и отбибитесь.... И вот приходится ковыряться со всем этим в одиночку. Ни с ПЛК ни с голым линуксом я до того дела не имел... К сожалению не пишу на C++ вообще и под Qt в частности. Но если Вы сможете собрать библиотеку Qt для Вашего target-а, то почему-бы и нет. У наших сотрудников получалось собирать и запускать программы с интерфейсом, написанным на Qt на ARM-овской плате TI4372, так-что это вполне возможно. Как они этого достигли - это второй вопрос - я не интересовался.
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #16 : 22-02-2018 11:07 » |
|
ещё один вопрос это уже касаемо сборки Qt под линуксом. может знает кто
в процессе сборки выдает ошибку
error: unused parameter ‘segmentSize’ [-Werror=unused-parameter]
полдня уже ищу как отключить перевод предупреждений в ошибки. пишут про флаги, но все про разные. и что самое непонятное - в какой файл их прописывать - в makefile коневой Qt или отдельно в makefile проекта в котором ошибка? и вообще может не в makefile, а ещё куда-то.
просьба только не ругаться. я в этом нихрена не понимаю. только начинаю разбираться.!!! подскажите пожалуйста!!
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #17 : 22-02-2018 12:03 » |
|
в процессе сборки выдает ошибку
error: unused parameter ‘segmentSize’ [-Werror=unused-parameter]
полдня уже ищу как отключить перевод предупреждений в ошибки.
Видимо где-то при сборке указан параметр -Werror. пишут про флаги, но все про разные. и что самое непонятное - в какой файл их прописывать - в makefile коневой Qt или отдельно в makefile проекта в котором ошибка? и вообще может не в makefile, а ещё куда-то.
ну, там где ругается, там и прописывать, если это при сборке приложения - прописывать у него, возможно как-то через *.pro-файл, если это при сборке Qt - прописывать в makefile, или что там сейчас у Qt. Кстати, у Вас на ПЛК тоже-ведь Linux стоит? как вариант, если есть место и не сильно торопитесь - можно поставить на сам ПЛК средства разработки - по крайней мере компилятор и devel-пакет Qt и собирать на самом ПЛК.
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #18 : 22-02-2018 12:10 » |
|
в процессе сборки выдает ошибку
error: unused parameter ‘segmentSize’ [-Werror=unused-parameter]
полдня уже ищу как отключить перевод предупреждений в ошибки.
Видимо где-то при сборке указан параметр -Werror. пишут про флаги, но все про разные. и что самое непонятное - в какой файл их прописывать - в makefile коневой Qt или отдельно в makefile проекта в котором ошибка? и вообще может не в makefile, а ещё куда-то.
ну, там где ругается, там и прописывать, если это при сборке приложения - прописывать у него, возможно как-то через *.pro-файл, если это при сборке Qt - прописывать в makefile, или что там сейчас у Qt. Кстати, у Вас на ПЛК тоже-ведь Linux стоит? как вариант, если есть место и не сильно торопитесь - можно поставить на сам ПЛК средства разработки - по крайней мере компилятор и devel-пакет Qt и собирать на самом ПЛК. и с этим разобрался. оказалось надо в команде config которая перед вызовом make указывать ключ специальный.... это просто жопа какая-то!!! сейчас вот собирается qt под линукс, но по скорости - видимо ещё пару дней будет собираться потом как-то надо сделать то же самое под arm а уж если на самом плк, то за полгода не соберется кстати вот возник у меня вопрос, boost - как альтернатива qt с бустом работать не приходилось. отзывы читаю разные. кто хвалит, кто ругает. на сколько я понимаю, это надстройка в виде библиотеки над c++, которая должна облегчать людям жизнь?
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #19 : 22-02-2018 13:21 » |
|
и с этим разобрался. оказалось надо в команде config которая перед вызовом make указывать ключ специальный.... это просто жопа какая-то!!! сейчас вот собирается qt под линукс, но по скорости - видимо ещё пару дней будет собираться
потом как-то надо сделать то же самое под arm а уж если на самом плк, то за полгода не соберется
Qt не надо будет собирать, надо будет взять тот, который идёт в дистрибутиве. Собирать надо будет только Ваш код. кстати вот возник у меня вопрос, boost - как альтернатива qt с бустом работать не приходилось. отзывы читаю разные. кто хвалит, кто ругает. на сколько я понимаю, это надстройка в виде библиотеки над c++, которая должна облегчать людям жизнь? Ну, Qt как-бы в основном для графики, хотя там есть и общие алгоритмы, а boost, как я понимаю, огромная библиотека с кучей разнообразной функциональности. Причём, как я понял, довольно очень сильно навороченная.
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #20 : 22-02-2018 13:58 » |
|
и с этим разобрался. оказалось надо в команде config которая перед вызовом make указывать ключ специальный.... это просто жопа какая-то!!! сейчас вот собирается qt под линукс, но по скорости - видимо ещё пару дней будет собираться
потом как-то надо сделать то же самое под arm а уж если на самом плк, то за полгода не соберется
Qt не надо будет собирать, надо будет взять тот, который идёт в дистрибутиве. Собирать надо будет только Ваш код. кстати вот возник у меня вопрос, boost - как альтернатива qt с бустом работать не приходилось. отзывы читаю разные. кто хвалит, кто ругает. на сколько я понимаю, это надстройка в виде библиотеки над c++, которая должна облегчать людям жизнь? Ну, Qt как-бы в основном для графики, хотя там есть и общие алгоритмы, а boost, как я понимаю, огромная библиотека с кучей разнообразной функциональности. Причём, как я понял, довольно очень сильно навороченная. сам qt - не надо, но все нужные библиотеки придется пересобрать под платформу arm. а иначе как оно работать будет на arm-е? приложение-то мое сиборается на на arm, а под линуксом на виртуалке. кросскомпилляция в общем сплошная.
|
|
« Последнее редактирование: 22-02-2018 13:59 от demon051 »
|
Записан
|
|
|
|
|