Ликбез по Линуксу: о таймерах

Простой и удобный способ организации работы с таймерами для множества однотипных объектов одновременно.

Используемые системные вызовы: timer_create, timer_settime, timer_gettime.

1. Создадим базовый виртуальный класс, приблизительно такой:

class ITimer
{
 public:
  ITimer();
  ~ITimer();
  void CreateTimer();
  void DestroyTimer();
  void On(time_t vTime);
  void On(time_t vTime,long lNanoSec);
  time_t IsActive();
  time_t IsEndTime();
  void Off();
  void Waiting();
  virtual bool DoAction()=0;
 sigset_t psig_maskFirst;
 siginfo_t psig_infoFirst;
 struct sigevent sevFirst;
 struct sigaction saFirst;
};

Функция CreateTimer() может быть приблизительно такая:

void ITimer::CreateTimer()
{
 int ilErrno;
 saFirst.sa_flags = SA_SIGINFO;
 saFirst.sa_sigaction = handler_timer;
 if (sigaction(SIGRTMIN, &saFirst, NULL) == -1)
 {
  ilErrno = errno;
  fprintf(stderr," error. sigaction %s\n", getpid(),strerror(ilErrno));
 }
 sevFirst.sigev_notify = SIGEV_SIGNAL;
 sevFirst.sigev_signo = SIGRTMIN;
 sevFirst.sigev_value.sival_ptr = this;
 if (timer_create(CLOCK_REALTIME, &sevFirst, (void **)&timerFirstId) == -1)
 {
  ilErrno = errno;
  fprintf(stderr,"error timer_create. %s\n", strerror(ilErrno));
 }
}

Особое внимание здесь надо обратить на строку:

sevFirst.sigev_value.sival_ptr = this;

2. Подготовим обработчик сигнала SIGRTMIN:

static void handler_timer(int sig, siginfo_t *si, void *uc)
{
 ITimer* opITimer;
 opITimer = (ITimer*)si->si_int;
 opITimer->DoAction();
}

3. Подготовим классы, наследующие этот базовый класс ITimer.

class CUser:public ITimer
{
 public:
  CUser();
  ~CUser();
  virtual bool DoAction();
};
//---------------------------------
bool CUser::DoAction()
{
 fprintf(stdout," User:: Hello Word!!! \n");
}

class CAbonent:public ITimer
{
 public:
  CAbonent();
  ~CAbonent();
  virtual bool DoAction();
};
//---------------------------------
bool CAbonent::DoAction()
{
 fprintf(stdout," Abonent:: Hello Word!!! \n");
}

class CUnit:public ITimer
{
 public:
  CUnit();
  ~CUnit();
  virtual bool DoAction();
};
//---------------------------------
bool CUnit::DoAction()
{
 fprintf(stdout," CUnit:: Hello Word!!! \n");
}

И так далее...

В результате, после создания и включения таймера для объектов, например, типа CAbonent, обработчик сигнала сразу, без всякого анализа вызовет нужную функцию DoAction().

Версия для печатиВерсия для печати

Рубрики: 

  • 1
  • 2
  • 3
  • 4
  • 5
Всего голосов: 0
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя mike
Слегка фигею от такого ликбеза. Видимо, предполагается, что человек знаком с используемыми структурами. ИМХО тут полезнее: http://www.qnx.com/developers/docs/6.4.1/neutrino/getting_started/s1_timer.html Разжёвано! Неплохо и тут: http://www.linuxhowtos.org/manpages/2/timer_create.htm или http://www.linuxcertif.com/man/2/timer_create/
Аватар пользователя Al
Согласен с Майком. Это не ликбез, это в лучшем случае кусок ликбеза. Без вводной части это только для тех, кто давно в теме, в одной команде.