demon051
Помогающий
Offline
|
|
« : 10-05-2018 11:15 » |
|
Всем привет! Есть таймер const int signoBM = SIGRTMIN + 2;
bool BaseModuleManager::createTimerBM() { siginfo_t info; struct sigevent sigev; struct sigaction sa; struct itimerspec ival;
/* Регистрируем обработчик для SIGRTMIN + 2*/
sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = timerHandlerBM; if (sigaction(signoBM, &sa, NULL) == -1) { return false; }
sigemptyset(&timerBMSigMask); sigaddset(&timerBMSigMask, signoBM);
sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = signoBM; sigev.sigev_value.sival_int = 2; sigev.sigev_value.sival_ptr = this;
sigprocmask(SIG_BLOCK, &timerBMSigMask, NULL);
if (timer_create(CLOCK_MONOTONIC, &sigev, &_tidBM) == -1) { return false; }
struct itimerspec ival; ival.it_value.tv_sec = 1; ival.it_value.tv_nsec = 0; ival.it_interval.tv_sec = 0; ival.it_interval.tv_nsec = 500000000;
if (timer_settime(_tidBM, 0, &ival, NULL) == -1) { return false; }
return true; }
bool BaseModuleManager::unblockTimerBM() { if (sigprocmask(SIG_UNBLOCK, &timerBMSigMask, NULL) == -1) return false; return true; }
Собственно, предполагается, что таймер не должен сразу стартовать, при создании. А должен при вызове unblockTimerBM() однако, запускается сразу. Вопрос: что делаю не так? И можно ли таким образом заблокировать сигнал таймера? Как правильно это сделать? Задача в том, чтобы по необходимости запускать и останавливать таймер. Для остановки думалось использовать bool BaseModuleManager::blockTimerBM() { if (sigprocmask(SIG_BLOCK, &timerBMSigMask, NULL) == -1) return false; return true; }
|
|
« Последнее редактирование: 10-05-2018 11:24 от demon051 »
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #1 : 10-05-2018 12:13 » |
|
Вопрос: что делаю не так?
Блокируете сигнал от таймера вместо блокировки самого таймера. Блокировка сигнала блокирует доставку, но не сбрасывает наличие сигнала, соответственно, как только Вы его разрешаете - он сразу и доставляется Вашей задаче. Имхо, лучше в bool BaseModuleManager::createTimerBM() создавать отключенный таймер: const int signoBM = SIGRTMIN + 2;
bool BaseModuleManager::createTimerBM() { siginfo_t info; struct sigevent sigev; struct sigaction sa;
/* Регистрируем обработчик для SIGRTMIN + 2*/
sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = timerHandlerBM; if (sigaction(signoBM, &sa, NULL) == -1) { return false; }
sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = signoBM; sigev.sigev_value.sival_int = 2; sigev.sigev_value.sival_ptr = this;
if (timer_create(CLOCK_MONOTONIC, &sigev, &_tidBM) == -1) { return false; }
return true; } А затем в bool BaseModuleManager::unblockTimerBM() запрограммировать его на нужный цикл: bool BaseModuleManager::unblockTimerBM() {
struct itimerspec ival; ival.it_value.tv_sec = 0; ival.it_value.tv_nsec = 500000000; ival.it_interval.tv_sec = 0; ival.it_interval.tv_nsec = 500000000; if (timer_settime(_tidBM, 0, &ival, NULL) == -1) { return false; } return true; } Если необходимо блокирование таймера, то оно выполняется следующим образом: bool BaseModuleManager::blockTimerBM() {
struct itimerspec ival = { 0 }; if (timer_settime(_tidBM, 0, &ival, NULL) == -1) { return false; } return true; }
|
|
« Последнее редактирование: 10-05-2018 12:20 от darkelf »
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #2 : 10-05-2018 13:17 » |
|
Вопрос: что делаю не так?
Блокируете сигнал от таймера вместо блокировки самого таймера. Блокировка сигнала блокирует доставку, но не сбрасывает наличие сигнала, соответственно, как только Вы его разрешаете - он сразу и доставляется Вашей задаче. Имхо, лучше в bool BaseModuleManager::createTimerBM() создавать отключенный таймер: const int signoBM = SIGRTMIN + 2;
bool BaseModuleManager::createTimerBM() { siginfo_t info; struct sigevent sigev; struct sigaction sa;
/* Регистрируем обработчик для SIGRTMIN + 2*/
sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = timerHandlerBM; if (sigaction(signoBM, &sa, NULL) == -1) { return false; }
sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = signoBM; sigev.sigev_value.sival_int = 2; sigev.sigev_value.sival_ptr = this;
if (timer_create(CLOCK_MONOTONIC, &sigev, &_tidBM) == -1) { return false; }
return true; } А затем в bool BaseModuleManager::unblockTimerBM() запрограммировать его на нужный цикл: bool BaseModuleManager::unblockTimerBM() {
struct itimerspec ival; ival.it_value.tv_sec = 0; ival.it_value.tv_nsec = 500000000; ival.it_interval.tv_sec = 0; ival.it_interval.tv_nsec = 500000000; if (timer_settime(_tidBM, 0, &ival, NULL) == -1) { return false; } return true; } Если необходимо блокирование таймера, то оно выполняется следующим образом: bool BaseModuleManager::blockTimerBM() {
struct itimerspec ival = { 0 }; if (timer_settime(_tidBM, 0, &ival, NULL) == -1) { return false; } return true; } спасибо за ответ. так уже делал. хотелось как бы поизящнее но видимо не судьба. и ещё тогда вопрос - читал где-то что вывод через printf в обработчике сигнала небезопасен. это так?
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #3 : 10-05-2018 13:51 » |
|
и ещё тогда вопрос - читал где-то что вывод через printf в обработчике сигнала небезопасен. это так?
Про printf в man-е есть даже объяснение, почему небезопасен
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #4 : 10-05-2018 20:20 » |
|
Прежде всего, опасайтесь в обработчике алоцировать память в куче. Очень легко получить дедлок на malloc(). Необходимые буфера алоцируйте заранее.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #5 : 11-05-2018 07:15 » |
|
и ещё тогда вопрос - читал где-то что вывод через printf в обработчике сигнала небезопасен. это так?
Про printf в man-е есть даже объяснение, почему небезопасен так... интересно... а если мне надо выводить сообщения на консоль из обработчика сигнала, то как это делается "правильно"?
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #6 : 11-05-2018 07:15 » |
|
и ещё тогда вопрос - читал где-то что вывод через printf в обработчике сигнала небезопасен. это так?
Про printf в man-е есть даже объяснение, почему небезопасен так... интересно... а если мне надо выводить сообщения на консоль из обработчика сигнала, то как это делается "правильно"? это вообще какой-то трэш....
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #7 : 11-05-2018 07:36 » |
|
Если хорошенько подумать, это не треш, а обработка сигнала — нечто вроде обработки прерывания в user space. Причем обработка не в другом потоке, а в том же, это надо помнить. Недопустимо блокироваться на взаимных блокировках, т.к. этот же поток уже может стоять на этой блокировке (см. выше про malloc). Память можно алоцировать только на стеке. Если нужна динамическая, об этом нужно позаботиться заранее, до прихода сигнала. Короче, поменьше изящных решений!
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #8 : 11-05-2018 08:00 » |
|
Если хорошенько подумать, это не треш, а обработка сигнала — нечто вроде обработки прерывания в user space. Причем обработка не в другом потоке, а в том же, это надо помнить. Недопустимо блокироваться на взаимных блокировках, т.к. этот же поток уже может стоять на этой блокировке (см. выше про malloc). Память можно алоцировать только на стеке. Если нужна динамическая, об этом нужно позаботиться заранее, до прихода сигнала. Короче, поменьше изящных решений! мдя... цензурных слов на ум приходит мало, чем дальше в лес... т.е. в unix а чо, давайте писать на ассемблере! там вааще ничего изящного акромя всяких безобразий!
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #9 : 11-05-2018 08:54 » |
|
и ещё тогда вопрос - читал где-то что вывод через printf в обработчике сигнала небезопасен. это так?
Про printf в man-е есть даже объяснение, почему небезопасен так... интересно... а если мне надо выводить сообщения на консоль из обработчика сигнала, то как это делается "правильно"? void sigint(int signo) { char* error_msg = "Усё пропало, хавайся у бульбу!\n" size_t error_len = strlen(error_msg);
write(2, error_msg, error_len); _exit(1); return ; } Например, так.
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #10 : 11-05-2018 09:02 » |
|
Причем обработка не в другом потоке, а в том же, это надо помнить.
Хотелось-бы немного поправить, что, если не предпринимать дополнительных действий, то обработка в ЛЮБОМ потоке, в том числе и в том же самом.
|
|
« Последнее редактирование: 11-05-2018 09:04 от darkelf »
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #11 : 11-05-2018 12:44 » |
|
и ещё тогда вопрос - читал где-то что вывод через printf в обработчике сигнала небезопасен. это так?
Про printf в man-е есть даже объяснение, почему небезопасен так... интересно... а если мне надо выводить сообщения на консоль из обработчика сигнала, то как это делается "правильно"? void sigint(int signo) { char* error_msg = "Усё пропало, хавайся у бульбу!\n" size_t error_len = strlen(error_msg);
write(2, error_msg, error_len); _exit(1); return ; } Например, так. т.е. write - потокобезопасна? но она же и без форматирования... UPD: ы-ы-ы-ыы.... зато strlen согласно спецификации так же не безопасна как и printf ОПА!
|
|
« Последнее редактирование: 11-05-2018 12:47 от demon051 »
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #12 : 11-05-2018 14:46 » |
|
т.е. write - потокобезопасна? но она же и без форматирования... UPD: ы-ы-ы-ыы.... зато strlen согласно спецификации так же не безопасна как и printf ОПА!
Посмотрите внимательнее: strlen(3) Added in POSIX.1-2016 А про форматирование - RXL правильно сказал - это типа обработок прерываний - какие в прерываниях могут быть форматирования? Для организации более удобного интерфейса с сигналами можно посмотреть в сторону signalfd, правда она очень linux-специфична.
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #13 : 11-05-2018 23:09 » |
|
А еще есть libev. Помимо асинхронщины, в том же потоке можно обрабатывать сигналы без ограничений. Но асинхронный подход требует не тупить в обработчиках событий, иначе что-то может работать не очень хорошо. Если нужно потупить, можно сделать это в другом потоке.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #14 : 13-05-2018 11:48 » |
|
т.е. write - потокобезопасна? но она же и без форматирования... UPD: ы-ы-ы-ыы.... зато strlen согласно спецификации так же не безопасна как и printf ОПА!
Посмотрите внимательнее: strlen(3) Added in POSIX.1-2016 А про форматирование - RXL правильно сказал - это типа обработок прерываний - какие в прерываниях могут быть форматирования? Для организации более удобного интерфейса с сигналами можно посмотреть в сторону signalfd, правда она очень linux-специфична. абсолютно элементарные форматирования строк для вывода на экран: printf("значение параметра %d \n", param)
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #15 : 13-05-2018 19:11 » |
|
Хочешь, чтобы что-то тебе сказал, "можно"? Жди дальше. А если хочешь разбираться в вопросе, бери исходники своей версии glibc и смотри, используется ли там динамическое выделение памяти.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #16 : 14-05-2018 05:06 » |
|
Хочешь, чтобы что-то тебе сказал, "можно"? Жди дальше. А если хочешь разбираться в вопросе, бери исходники своей версии glibc и смотри, используется ли там динамическое выделение памяти.
вот уё.... система этот глинукс. это я ещё зачем-то должен исходники библиотек смотреть. а ага и перейти на топоры из кремня и огонь разводить трением.
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #17 : 14-05-2018 05:54 » |
|
Хочешь, чтобы что-то тебе сказал, "можно"? Жди дальше. А если хочешь разбираться в вопросе, бери исходники своей версии glibc и смотри, используется ли там динамическое выделение памяти.
вот уё.... система этот глинукс. это я ещё зачем-то должен исходники библиотек смотреть. а ага и перейти на топоры из кремня и огонь разводить трением. Вроде как Opensource - никто за Вас не обязан в исходники смотреть, если это нужно только Вам. Как вариант - можете оплатить работу энтузиаста, который это сделает за Вас, правда для конкретной версии ядра и конкретной версии libc. Вообще, каждая система имеет свои удачные и неудачные особенности. Плюс, как уже говорилось раньше - изначально сигналы были придуманы как аналог прерываний и предназначались, имхо, немного для другого - сбить с блокирующего системного вызова. Т.е. ожидаем мы приёма сообщения, например, через UART, а его всё нет и нет, пользователю надоело ждать и он хочет прервать это тягостное ожидание. Он жмёт Ctrl+C, и текущему приложению прилетает сигнал SIGINT, если нет обработчика или блокировки - процесс убивается на месте. Если есть обработчик - у процесса появляется шанс как-то перед завершением за собой почистить - файлы удалить, может ещё что. Аналогично было сделано и завершение сеанса работы - если пользователь запустил некоторое количество задач, а потом отлогинился (мы-же помним, что изначально unix-системы были многопользовательские, с возможно даже оплачиваемым временем доступа), то его задачи надо как-то завершить - так вот было придумано, что сигнал посылается группе процессов, эта группа создаётся при входе в систему программой входа и наследуются потом всеми процессами, которые запускает пользователь. А дальше уже к сигналам стали привешивать и таймера, возможность передачи дополнительной информации и другие вещи. Тут уже посоветовали переносимую libev, есть ещё libevent и ещё, по-моему, несколько подобных библиотек, а если хочется не зависеть от сторонних библиотек, но быть завязанным на linux - есть, кроме упомянутого signalfd(), ещё и timerfd_*(), который позволяет без всяких сигналов обеспечивать работу с таймерами. Менее производительный, но более портабельный вариант - завести пару связанных файловых дескрипторов через pipe() или socketpair(), и на одном его конце ожидать события, а в обработчике сигнала по необходимости писать в другой конец - так получение сигнала тоже будет трансформироваться в событие на файловом дескрипторе, доступное к мониторингу через select()/poll(). Кстати, раз пошел такой разговор - зачем Вам форматированный вывод в обработчике сигнала. В смысле - у Вас есть конкретная задача, и там надо выводить форматированный текст? Так, конечно, если-бы в обработчиках сигналов работали fprintf() и вообще любые функции, любой степень сложности, вплоть до разбора xml-ей и прочих json-ов, было-бы неплохо, но, как говорится, "маемо тэ, що маемо".
|
|
« Последнее редактирование: 14-05-2018 05:58 от darkelf »
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #18 : 14-05-2018 07:17 » |
|
Хочешь, чтобы что-то тебе сказал, "можно"? Жди дальше. А если хочешь разбираться в вопросе, бери исходники своей версии glibc и смотри, используется ли там динамическое выделение памяти.
вот уё.... система этот глинукс. это я ещё зачем-то должен исходники библиотек смотреть. а ага и перейти на топоры из кремня и огонь разводить трением. Вроде как Opensource - никто за Вас не обязан в исходники смотреть, если это нужно только Вам. Как вариант - можете оплатить работу энтузиаста, который это сделает за Вас, правда для конкретной версии ядра и конкретной версии libc. Вообще, каждая система имеет свои удачные и неудачные особенности. Плюс, как уже говорилось раньше - изначально сигналы были придуманы как аналог прерываний и предназначались, имхо, немного для другого - сбить с блокирующего системного вызова. Т.е. ожидаем мы приёма сообщения, например, через UART, а его всё нет и нет, пользователю надоело ждать и он хочет прервать это тягостное ожидание. Он жмёт Ctrl+C, и текущему приложению прилетает сигнал SIGINT, если нет обработчика или блокировки - процесс убивается на месте. Если есть обработчик - у процесса появляется шанс как-то перед завершением за собой почистить - файлы удалить, может ещё что. Аналогично было сделано и завершение сеанса работы - если пользователь запустил некоторое количество задач, а потом отлогинился (мы-же помним, что изначально unix-системы были многопользовательские, с возможно даже оплачиваемым временем доступа), то его задачи надо как-то завершить - так вот было придумано, что сигнал посылается группе процессов, эта группа создаётся при входе в систему программой входа и наследуются потом всеми процессами, которые запускает пользователь. А дальше уже к сигналам стали привешивать и таймера, возможность передачи дополнительной информации и другие вещи. Тут уже посоветовали переносимую libev, есть ещё libevent и ещё, по-моему, несколько подобных библиотек, а если хочется не зависеть от сторонних библиотек, но быть завязанным на linux - есть, кроме упомянутого signalfd(), ещё и timerfd_*(), который позволяет без всяких сигналов обеспечивать работу с таймерами. Менее производительный, но более портабельный вариант - завести пару связанных файловых дескрипторов через pipe() или socketpair(), и на одном его конце ожидать события, а в обработчике сигнала по необходимости писать в другой конец - так получение сигнала тоже будет трансформироваться в событие на файловом дескрипторе, доступное к мониторингу через select()/poll(). Кстати, раз пошел такой разговор - зачем Вам форматированный вывод в обработчике сигнала. В смысле - у Вас есть конкретная задача, и там надо выводить форматированный текст? Так, конечно, если-бы в обработчиках сигналов работали fprintf() и вообще любые функции, любой степень сложности, вплоть до разбора xml-ей и прочих json-ов, было-бы неплохо, но, как говорится, "маемо тэ, що маемо". приходится делать софт для ПЛК. в обработчиках делаю вывод отладки. там определенная информация от прибора, которую надо представить в понятном для визуального восприятия виде. понятно, что в конечном варианте ничего выводиться на консоль не будет. хотя тоже как посмотреть. например для пусконаладки вывод на консоль весьма полезен. основной код написан. и вот теперь упираемся в то, что оно в режиме вывода на консоль просто валится. переделывать и переводить на другие библиотеки из-за такой муры??? беда в том, что с линуксом ранее не работали на таком низком уровне. поэтому и попали в такую ситуацию. никто даже и не предполагал, что такое унылое Г может произойти...
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #19 : 14-05-2018 07:33 » |
|
demon051, чтение исходников чего-либо — норма для разработчика. А наличие исходников в открытом доступе — благо. Типичная ситуация: обнаружил ты странное поведение сложной программы, в разработке которой принимаешь участие, подебажил малость и нашел, что странность в сторонней библиотеке. Что дальше? Обычно начинается гуглеж, но бывает, что он бесполезен. Тогда берешь исходники (благо большинство библиотек пишутся профессионалами на Си, а не вчерашними выпускниками вузов на пижонских питонах и иже с ними), смотришь свою версию библиотеки, отматываешь на соотв. ревизию и углубляешься в код. Удивительное рядом: обнаруживаешь, что бага есть и она исправлена в такой-то версии. Т.е. достаточно обновиться до этой версии. Казалось бы, а почему не взять самую свежую? А тут могут быть проблемы: библиотека имеет свои внешние зависимости и может потянуть апгрейд других библиотек, не всегда совместимый с существующим окружением. Апгрейд на минимальную требуемую версию безопасней. А теперь тоже самое, но для закрытых исходников. Гуглеж даже для MS может быть бесполезен, а обращение в саппорт (а если у тебя право туда обращаться?) может занять неопределенное время. Либо у тебя очень высокая квалификация и ты сможешь самостоятельно разобраться, либо начинается шаманство и перебор версий SDK, как тут.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
RXL
|
|
« Ответ #20 : 14-05-2018 07:34 » |
|
приходится делать софт для ПЛК. в обработчиках делаю вывод отладки. там определенная информация от прибора, которую надо представить в понятном для визуального восприятия виде. понятно, что в конечном варианте ничего выводиться на консоль не будет. хотя тоже как посмотреть. например для пусконаладки вывод на консоль весьма полезен. основной код написан. и вот теперь упираемся в то, что оно в режиме вывода на консоль просто валится. переделывать и переводить на другие библиотеки из-за такой муры??? беда в том, что с линуксом ранее не работали на таком низком уровне. поэтому и попали в такую ситуацию. никто даже и не предполагал, что такое унылое Г может произойти...
Не умеешь, не берись. Взялся, подумай головой. Можно в обработчике сигнала поднять флаг (логическую переменную, заранее сброшенную), а в основной программе это обнаружить и распечатать. Аналогично передача данных из обработчика.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #21 : 14-05-2018 08:48 » |
|
приходится делать софт для ПЛК. в обработчиках делаю вывод отладки. там определенная информация от прибора, которую надо представить в понятном для визуального восприятия виде. понятно, что в конечном варианте ничего выводиться на консоль не будет. хотя тоже как посмотреть. например для пусконаладки вывод на консоль весьма полезен. основной код написан. и вот теперь упираемся в то, что оно в режиме вывода на консоль просто валится. переделывать и переводить на другие библиотеки из-за такой муры??? беда в том, что с линуксом ранее не работали на таком низком уровне. поэтому и попали в такую ситуацию. никто даже и не предполагал, что такое унылое Г может произойти...
Не умеешь, не берись. Взялся, подумай головой. Можно в обработчике сигнала поднять флаг (логическую переменную, заранее сброшенную), а в основной программе это обнаружить и распечатать. Аналогично передача данных из обработчика. приложение много поточное, умаешся везде флаги поднимать. можно организовать кучу очередей с мьютексами. и выводить где-то и когда-то. но выводить надо - как только данные поступили.
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #22 : 14-05-2018 09:01 » |
|
demon051, имхо, имеется в виду в обработчике просто выставлять факт получения сигнала. т.е. sigatomic_t got_sigint;
void sigint(int signo) { got_sigint = 1; return ; }
int main(int argc, char* argv[]) { ... if (got_sigint) { printf("мы получили SIGINT - нас хотят прервать!\n"); got_sigint = 0; } ... } Просто, похоже, Вы пытаетесь использовать сигналы не совсем таким способом, для какого они были придуманы. Вы данные получаете в обработчике сигнала?
|
|
« Последнее редактирование: 14-05-2018 09:09 от darkelf »
|
Записан
|
|
|
|
Sla
|
|
« Ответ #23 : 14-05-2018 10:03 » |
|
Задача обработчика сигнала, обработать сигнал, и отдать в "поток" А не в обработчиках делаю вывод отладки.
Зачем человко вывод? Опять же, вывод в консоль - это тоже прерывание система этот глинукс.
А сделайте тоже самое под виндой Станет проще? хотелось как бы поизящнее Улыбаюсь но видимо не судьба.
Куда еще изящнее? хотя тоже как посмотреть. например для пусконаладки вывод на консоль весьма полезен.
Пишется дебажный код, который слушает результат работы таймера и выводит в консоль. Таймер сам по себе, консоль сама по себе, потому что время вывода, несопоставимо со временем обработки сигнала. Даже если это не сигнал, а фоновая обработка данных = прерывание. прерывание - только обработка, максимум - подготовка к выводу.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #24 : 14-05-2018 13:42 » |
|
Задача обработчика сигнала, обработать сигнал, и отдать в "поток" А не в обработчиках делаю вывод отладки.
Зачем человко вывод? Опять же, вывод в консоль - это тоже прерывание система этот глинукс.
А сделайте тоже самое под виндой Станет проще? хотелось как бы поизящнее Улыбаюсь но видимо не судьба.
Куда еще изящнее? хотя тоже как посмотреть. например для пусконаладки вывод на консоль весьма полезен.
Пишется дебажный код, который слушает результат работы таймера и выводит в консоль. Таймер сам по себе, консоль сама по себе, потому что время вывода, несопоставимо со временем обработки сигнала. Даже если это не сигнал, а фоновая обработка данных = прерывание. прерывание - только обработка, максимум - подготовка к выводу. ради интереса стал делать так: при входе в процедуру обработчик таймерного тика останавливают таймер, после завершения всех операций в обрабочике, стартую таймер. работает. но не очень долго выдерживает от 500 до 2000 рестартов. потом таймер отказывается рестартовать. не сталкивались с таким?
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #25 : 14-05-2018 13:42 » |
|
demon051, имхо, имеется в виду в обработчике просто выставлять факт получения сигнала. т.е. sigatomic_t got_sigint;
void sigint(int signo) { got_sigint = 1; return ; }
int main(int argc, char* argv[]) { ... if (got_sigint) { printf("мы получили SIGINT - нас хотят прервать!\n"); got_sigint = 0; } ... } Просто, похоже, Вы пытаетесь использовать сигналы не совсем таким способом, для какого они были придуманы. Вы данные получаете в обработчике сигнала? да, в нем. вернее, в обработчике сигнала я извлекаю данные из очереди, куда они складываются другим потоком. интересный момент обнаружился кроме всего прочего, таймер не выдерживает многократные рестарты. как рассматривалось выше. т.е. получив очередной тик таймера, а его останавливаю, выполнив операцию с данными - запускаю снова. до 2000 раз такая операция проходит.потом или даже ранее - таймер отказывается стартовать. прям беда-беда какая-то
|
|
« Последнее редактирование: 14-05-2018 13:45 от demon051 »
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #26 : 14-05-2018 14:58 » |
|
интересный момент обнаружился кроме всего прочего, таймер не выдерживает многократные рестарты. как рассматривалось выше. т.е. получив очередной тик таймера, а его останавливаю, выполнив операцию с данными - запускаю снова. до 2000 раз такая операция проходит.потом или даже ранее - таймер отказывается стартовать. прям беда-беда какая-то И как он это аргументирует? что пишет в errno?
|
|
|
Записан
|
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #27 : 14-05-2018 15:12 » |
|
интересный момент обнаружился кроме всего прочего, таймер не выдерживает многократные рестарты. как рассматривалось выше. т.е. получив очередной тик таймера, а его останавливаю, выполнив операцию с данными - запускаю снова. до 2000 раз такая операция проходит.потом или даже ранее - таймер отказывается стартовать. прям беда-беда какая-то И как он это аргументирует? что пишет в errno? errno не разбирал. вычислил, надеюсь, что вычислил, методом тыка и тика что он не очень любит когда его рестартуют из его же колбэчной функции. хотя пока это ещё только гипотеза. сделал в колбэке отправку сигнала на рестарт, а сам рестарт - в обработчике этого сигнала. 6000 тысяч подряд раз рестартовался по-честному с обработкой событий из очереди. больше надоело проверять. но есть ещё один нюанс... это я с одним таймером мудохался, а так их три штуки одновременно пашет. завтра попробую задействовать остальные. посмотрю на результат. может влияет ещё и кол-во одновременно работающих таймеров (у каждого своя очередь с данными от разных источников и они никак не пересекаются). в общем чудеса сплошные с этой великолепной ОС. Добавлено через 2 минуты и 22 секунды:система этот глинукс.
А сделайте тоже самое под виндой Станет проще? [/quote] под виндой делалось ещё и не такое как часы, панимаишь. свои нюансы конечно есть, но извратов на 100 порядков меньше. ну может просто привык уже, пишу на автопилоте под винду )
|
|
« Последнее редактирование: 14-05-2018 15:20 от demon051 »
|
Записан
|
|
|
|
Sla
|
|
« Ответ #28 : 14-05-2018 16:53 » |
|
не знаю, я запускал три или четыре таймера, мало того, это все работало под тиклем и писало и в консоль и Панель, а еще успевало отдавать управление во внешний контроллер.
А зачем таймер останавливать на время обработки?
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
demon051
Помогающий
Offline
|
|
« Ответ #29 : 15-05-2018 09:17 » |
|
не знаю, я запускал три или четыре таймера, мало того, это все работало под тиклем и писало и в консоль и Панель, а еще успевало отдавать управление во внешний контроллер.
А зачем таймер останавливать на время обработки?
да как-то не понравилось мне как таймер работает. пишут, что тики ставятся в очередь, и не могут пересекаться. а на деле... операции разные по продолжительности выполняются. одна в интервал между тиками укладывается, другая - нет. и усё. приплыли. можно конечно критическими секциями заморочиться... но это если окажется что рестарт таймера сильно влияет на производительность... будем наблюдать. а по итогу - рестарт в обработчике сигнала посланного из обработчика таймерного тика вроде спас. два таймера работают. рестартуешь из обработчика тика - валится через какое-то время. чудны дела твои, линукс
|
|
|
Записан
|
|
|
|
|