Search code examples
c++clinuxtimersampling

How to setup a "precise" periodic timer to monitor stuff in Linux(C/C++)?


I am playing around with monitoring stuff. For that I like to monitor pins etc. on a regular base. The monitoring app should run in user space and be written in C/C++. I am looking for a good practice how to approach this field of problems generally.

There is a good answer about using timers already here. My question is more general nature. Are timers the best solutions or maybe a wait for a semaphore with a timeout? etc.

I put some pseudo code as a base for the discussion:

// 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));
  }
}

I am looking for solutions, to sample signals etc. periodically, like to detect/measure the jitter in between two samples and use a function for obtaining the sample signal data.

Any ideas are welcome!


Solution

  • use the function: setitimer() here is simple example:

    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);
    

    And catch the timer on a regular interval by using struct sigaction.

    Here is a simple example of using: struct sigaction:

    struct sigaction psa;
    psa.sa_handler = pSigHandler;   // << use the name of your signal hander
    sigaction(SIGTSTP, &psa, NULL);
    

    and here is a simple implementation of the function: pSigHandler()

    static void pSigHandler(int signo)
    {
        switch (signo) 
        {
                case SIGTSTP:
                    printf("TSTP");
                    fflush(stdout);
                    break;
        }
    }
    

    Of course, for all the above to work, need the two following statements:

    #include <stdio.h>
    #include <signal.h>
    

    There is a problem with the above code, There is a long list of functions that 'should' not be used in a signal handler. printf() is one of the problematic functions. My suggest is just have the signal handler function set a flag and the main function watching that flag and when found 'set', reset it and perform the necessary activities.