Как настроить & quot; точный & quot; периодический таймер для мониторинга вещей в Linux (C / C ++)?

Я играю с мониторингом. Для этого мне нравится регулярно следить за булавками и т. Д. Приложение для мониторинга должно работать в пространстве пользователя и быть написано на 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));
}
}

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

Любые идеи приветствуются!

0

Решение

используйте функцию: 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() является одной из проблемных функций. Я предлагаю просто установить функцию обработчика сигнала, установить флаг, а основную функцию — наблюдать за этим флагом, а при обнаружении «установить» сбросить его и выполнить необходимые действия.

1

Другие решения

Вы должны предположить, что 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) и он все равно будет достигать целевой частоты в долгосрочной перспективе (просто как крайний пример для реализации режима сна, который когда-либо спит только вдвое дольше, чем требуется).

1

Нет, это не подойдет для ваших целей. Linux не является ОСРВ, и нет абсолютно никакой гарантии, что ваш процесс будет пробужден в запрошенное время. Это даже не вопрос C ++, это вопрос ОС.

Лучший способ добиться того, что вы делаете в Linux, о которой я знаю, — это привязать процесс в режиме реального времени к изолированному ЦП, занимая занятое ожидание и ожидая, пока определенное количество циклов ЦП пройдет до следующего примера.

1

Я не буду навязывать, как вы должны использовать потоки, так как это зависит от вашего другого кода.
С 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);
0
По вопросам рекламы [email protected]