如何在linux中实现2个定时器

时间:2017-07-21 08:48:31

标签: c linux timer

我试图设置标志变量(使用raspbery pi。我需要引脚)持续500秒(微秒)并连续标记300秒(无限直到我停止它)。我想过使用2个定时器来实现它。

现在在这个程序中我写了5秒3秒。

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>

struct sigaction sa;
struct itimerval timer1,timer2;
 int count=1;
void timer_handler (int signum)
{
 if(count++%2==1)
    printf("High\n"); //flag=1
 else  
    printf("Low\n");   //flag=0
}

 int main ()
{


 /* Install timer_handler as the signal handler for SIGVTALRM. */
 memset (&sa, 0, sizeof (sa));
 sa.sa_handler = &timer_handler;
 sa.sa_flags = SA_RESTART;
 sigaction (SIGALRM, &sa, NULL);


 int i=0;
 while(1){
    scanf(" %d",&i);
    if(i==1){  // I m starting 2 timers here 
 timer1.it_value.tv_sec = 0;
 timer1.it_value.tv_usec = 1;
 timer1.it_interval.tv_sec = 8; //5+3
 timer1.it_interval.tv_usec = 0;

 timer2.it_value.tv_sec = 5;
 timer2.it_value.tv_usec = 0;
 timer2.it_interval.tv_sec = 8;
 timer2.it_interval.tv_usec = 0;
 setitimer (ITIMER_REAL, &timer1, NULL);
  setitimer (ITIMER_REAL, &timer2, NULL);
 }
 else if(i==2)  // I m stopping here 
 {
    timer1.it_value.tv_sec = 0;
 timer1.it_value.tv_usec = 0;
 timer1.it_interval.tv_sec = 0;
 timer1.it_interval.tv_usec = 0;

 timer2.it_value.tv_sec = 0;
 timer2.it_value.tv_usec = 0;
 timer2.it_interval.tv_sec = 0;
 timer2.it_interval.tv_usec = 0;
 setitimer (ITIMER_REAL, &timer1, NULL);   // 1st timer on
  setitimer (ITIMER_REAL, &timer2, NULL);  //2nd timer on 

 }
}
}

这是我写的代码。 实际发生的是第二个计时器正在运行并且第一个计时器未运行。我认为它被覆盖了。

聚苯乙烯。我不想使用睡眠功能,因为它需要更多的时间。我使用计时器,因为分辨率是微秒。

1.如何使用两个计时器进行此操作?
2.有没有更好的方法来完成这项任务?

1 个答案:

答案 0 :(得分:1)

只有一个ITIMER_REAL,因此您必须自己创建虚拟计时器。如果您不需要微秒精度,那么简单可靠的可能性就是使用间隔较小的周期性计时器并在此基础上实现虚拟计时器(所以每个&#34; tick &#34;来自您的定期计时器将减少您的虚拟计时器。)

按照示例说明如何实现它:

vtimer.h

#ifndef VTIMER_H
#define VTIMER_H

typedef void (vtimer_timeout)(void *arg);

typedef struct vtimer
{
    int msec;
    int periodic;
    int current;
    vtimer_timeout *timeout;
} vtimer;

#define vtimer_init(m, p, cb) { \
    .msec=(m), .periodic=(p), .current=0, .timeout=cb}

void vtimer_start(vtimer *self, void *timeoutArg);
void vtimer_stop(vtimer *self);

// call this periodically, e.g. after each interrupted library call:
void vtimer_dispatch();

#endif

vtimer.c

#define _POSIX_C_SOURCE 200101L

#include "vtimer.h"

#include <stddef.h>
#include <signal.h>
#include <sys/time.h>

#define NUM_TIMERS 8

static vtimer *timers[NUM_TIMERS] = {0};
static void *timoutArgs[NUM_TIMERS] = {0};

static size_t ntimers = 0;

static volatile sig_atomic_t ticks = 0;

static void tickhandler(int signum)
{
    (void)signum;
    ++ticks;
}

static struct sigaction timerAction = {.sa_handler = tickhandler};
static struct sigaction defaultAction;
static struct itimerval tickTimerval = {{0, 1000}, {0, 1000}};
static struct itimerval disableTimerval = {{0,0},{0,0}};

void vtimer_start(vtimer *self, void *timeoutArg)
{
    int found = 0;
    for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
    {
        if (timers[idx] == self)
        {
            found = 1;
            break;
        }
    }

    if (!found)
    {
        if (ntimers == NUM_TIMERS) return; // or maybe return error
        if (!ntimers++)
        {
            // only start the "ticking" timer when necessary
            sigaction(SIGALRM, &timerAction, &defaultAction);
            setitimer(ITIMER_REAL, &tickTimerval, 0);
        }
        for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
        {
            if (!timers[idx])
            {
                timers[idx] = self;
                timoutArgs[idx] = timeoutArg;
                break;
            }
        }
    }
    self->current = self->msec;
}

void vtimer_stop(vtimer *self)
{
    int found = 0;
    for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
    {
        if (timers[idx] == self)
        {
            timers[idx] = 0;
            found = 1;
            break;
        }
    }

    if (found && !--ntimers)
    {
        // no virtual timers running -> stop ticking timer
        setitimer(ITIMER_REAL, &disableTimerval, 0);
        sigaction(SIGALRM, &defaultAction, 0);
    }
}

void vtimer_dispatch(void)
{
    while (ticks)
    {
        --ticks;
        for (size_t idx = 0; idx < NUM_TIMERS; ++idx)
        {
            if (timers[idx])
            {
                if (!--(timers[idx]->current))
                {
                    timers[idx]->timeout(timoutArgs[idx]);
                    if (timers[idx]->periodic)
                    {
                        timers[idx]->current = timers[idx]->msec;
                    }
                    else vtimer_stop(timers[idx]);
                }
            }
        }
    }
}

使用此示例程序:

#include "vtimer.h"

#include <stdio.h>
#include <errno.h>

static void timer1_timeout(void *arg)
{
    (void) arg;
    puts("timer 1");
}

static void timer2_timeout(void *arg)
{
    (void) arg;
    puts("timer 2");
}

int main(void)
{
    vtimer timer1 = vtimer_init(5000, 1, timer1_timeout);
    vtimer timer2 = vtimer_init(8000, 1, timer2_timeout);

    vtimer_start(&timer1, 0);
    vtimer_start(&timer2, 0);

    for (;;)
    {
        errno = 0;
        int c = getchar();
        if (c == EOF && errno != EINTR) break;
        if (c == 'q') break;
        vtimer_dispatch();
    }

    vtimer_stop(&timer2);
    vtimer_stop(&timer1);
    return 0;
}

在路上有很多设计决策(例如你的刻度应该是多少(这里是1ms),具有固定数量的虚拟计时器而不是动态计时器,使用指针作为&#34;计时器处理&#34;或者整数,等等),所以想想你需要什么,并尝试自己编写。