Я играю с мониторингом. Для этого мне нравится регулярно следить за булавками и т. Д. Приложение для мониторинга должно работать в пространстве пользователя и быть написано на C / C ++. Я ищу хорошую практику, как подходить к этой области проблем в целом.
Есть хороший ответ об использовании таймеров уже Вот. Мой вопрос носит более общий характер. Таймеры — лучшее решение или, может быть, ожидание семафора с таймаутом? и т.п.
Я положил некоторый псевдокод в качестве основы для обсуждения:
// sample with 1kHz
#define fs 1000
// sample time
#define Ts 1.0/fs
// sample data structure
typedef struct sampleStruct {
struct timespec ts;
int sampleData[10];
} sampleType;
void monitorCallback(sampleType * pS) {
}
void sampleThread() {
sampleType s;
struct timespec workingtime;
for (;;) {
// get a timestamp
timespec_get(&(s.ts), TIME_UTC);
// sample data
monitorCallback(s);
// try to measure the time we spent for obtaining the sample
timespec_get(&workingtime, TIME_UTC);
// try to minimize the jitter by correcting the sleeping time
sleep(Ts - (workingtime - s.ts));
}
}
Я ищу решения для периодической выборки сигналов и т. Д., Например, для обнаружения / измерения джиттера между двумя выборками и использования функции для получения данных выборочных сигналов.
Любые идеи приветствуются!
используйте функцию: setitimer()
Вот простой пример:
struct itimerval tv;
tv.it_interval.tv_sec = 0;
tv.it_interval.tv_usec = 100000; // when timer expires, reset to 100ms
tv.it_value.tv_sec = 0;
tv.it_value.tv_usec = 100000; // 100 ms == 100000 us
setitimer(ITIMER_REAL, &tv, NULL);
И ловить таймер на регулярной основе, используя struct sigaction
,
Вот простой пример использования: struct sigaction
:
struct sigaction psa;
psa.sa_handler = pSigHandler; // << use the name of your signal hander
sigaction(SIGTSTP, &psa, NULL);
и вот простая реализация функции: pSigHandler()
static void pSigHandler(int signo)
{
switch (signo)
{
case SIGTSTP:
printf("TSTP");
fflush(stdout);
break;
}
}
Конечно, чтобы все вышеперечисленное работало, нужны два следующих утверждения:
#include <stdio.h>
#include <signal.h>
Существует проблема с приведенным выше кодом. Существует длинный список функций, которые «не должны» использоваться в обработчике сигналов. printf()
является одной из проблемных функций. Я предлагаю просто установить функцию обработчика сигнала, установить флаг, а основную функцию — наблюдать за этим флагом, а при обнаружении «установить» сбросить его и выполнить необходимые действия.
Вы должны предположить, что sleep()
а также «измерение времени мониторинга» очень неточно.
Если вы хотите отслеживать вещи через регулярные промежутки времени, вы должны изменить свой код, чтобы дождаться следующего интересного момента времени, например:
void sampleThread() {
sampleType s;
for (;;) {
// get a timestamp
timespec_get(&(s.ts), TIME_UTC);
// sample data
monitorCallback(s);
// Wait until the next sampling time.
struct timespec now;
timespec_get(&now, TIME_UTC);
sleep(now - s.ts);
}
}
Наиболее важным моментом является сон / ожидание до следующего абсолютного момента времени и вычисление этого следующего абсолютного момента времени исключительно на основе вашего целевого интервала, а не на основе какого-либо измеренного времени или чего-либо еще. Таким образом, любые неточности в sleep()
и во время исполнения не имеет значения вообще. В приведенном выше коде вы можете заменить sleep()
позвонить с sleep((now - s.ts) / 2)
и он все равно будет достигать целевой частоты в долгосрочной перспективе (просто как крайний пример для реализации режима сна, который когда-либо спит только вдвое дольше, чем требуется).
Нет, это не подойдет для ваших целей. Linux не является ОСРВ, и нет абсолютно никакой гарантии, что ваш процесс будет пробужден в запрошенное время. Это даже не вопрос C ++, это вопрос ОС.
Лучший способ добиться того, что вы делаете в Linux, о которой я знаю, — это привязать процесс в режиме реального времени к изолированному ЦП, занимая занятое ожидание и ожидая, пока определенное количество циклов ЦП пройдет до следующего примера.
Я не буду навязывать, как вы должны использовать потоки, так как это зависит от вашего другого кода.
С C ++ 11 есть модуль манипуляции временем (std::chrono
) в стандартной библиотеке. Используйте это с std::this_thread::sleep_until
:
#include <chrono>
#include <thread>
// ... in your code ...
namespace chr = std::chrono;
// steady_clock is better than system_clock in this case.
// You should also consider high_resolution_clock.
auto currentTime = chr::steady_clock::now();
auto targetTime = currentTime + chr::seconds{30};
// sleep until the targetTime
std::this_thread::sleep_until(targetTime);