Solved

Programming an asynchronous timer on Linux

Posted on 1998-12-24
6
345 Views
Last Modified: 2013-12-26
I have worked a bit on IBM AIX 4.1.2 and there I had a function called timeout() which would call my given routine every period of time specified. I would like to have the same thing on Linux, I searched for something like timeout() all through the manuals and could not find it.
Ofcourse, I could use select() but that cannot (?) be used asynchronously, i.e the program execution stops until select(| returns.
I am willing to give high points, because it is really important to me, please, HELP!
0
Comment
Question by:nir_m_
6 Comments
 
LVL 4

Expert Comment

by:jos010697
ID: 1294987
Have you tried the 'alarm' man page?

kind regards,

Jos aka jos@and.nl
0
 
LVL 2

Expert Comment

by:bertvermeerbergen
ID: 1294988
Using alarm() and setting up a signal handler that contains the code you want executed is somewhat similar.  There are limitations on what you can do in a signal handler, and alarm() allows you to specify full seconds only, no fractions.  Also, you need to make sure that a system call that is active when the alarm goes off (like select, wait, ...) is restarted, either by your code (checking for errno EINTR) or by the signal implementation itself.  The latter is possible with sigaction() and the other POSIX signal functions, but not (I believe) when using the simple signal() implementation.
0
 

Author Comment

by:nir_m_
ID: 1294989
No, I can't use alarm, I need a greater accuracy than full seconds.
0
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
LVL 2

Accepted Solution

by:
rdelfino earned 200 total points
ID: 1294990
In Solaris I have setitimer().

It sets a timer which has greater accuracy than alarm.

If you don't have this function, I suggest you creating a thread that implements the timer
you want.

Something like this:

#define _REENTRANT
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <pthread.h>

pthread_attr_t attr;
pthread_t tidTimer;

void *timerThread(void *args);

void yourHandler(int sig);
int main(void)
{
  struct sigaction act;
  sigset_t sigset;
  sigemptyset(&sigset);
  sigaddset(&sigset,SIGALRM);
  sigprocmask(SIG_BLOCK, &sigset, NULL);
 
  act.sa_handler = yourHandler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = SA_SIGINFO;
  sigaction(SIGALRM, &act, NULL);

  pthread_attr_init(&attr);
  pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
       
  pthread_create(&tidTimer,  &attr, timerThread, NULL);
 
  /* your program comes here */
 
  return 0;

}

void *timerThread(void *args)
{
  struct timeval timeOut;
  timeOut.tv_sec = 5; /* number of seconds */
  timeOut.tv_usec = 8; /* number of nanoseconds */
  for(;;)
  {
    select(0, NULL, NULL, NULL, &timeOut);
    kill(SIGALRM, getpid());
  }
  return NULL;
}

void yourHandler(int sig)
{
  /* do what you need here */
}


0
 
LVL 2

Expert Comment

by:rdelfino
ID: 1294991

Sorry,  I forgot to unblock the SIGALRM.

insert the following lines right before pthread_create():

sigfillset(&sigset);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);

0
 
LVL 2

Expert Comment

by:bertvermeerbergen
ID: 1294992
If you need sub-second accuracy but you can use the signal handler routine for your code, the solution can be to use setitimer().  This is somewhat similar to alarm(), but lets you specify the delay in seconds + microseconds, much like the select() call.  This call lets you set an interval for a timer that will raise a signal (SIGALRM or another, depending on the options) repeatedly.  Check out the man page for setitimer()/getitimer() for the argument types.
Remark that the microsecond specification is optimistic, normally you will get no more than a 10 millisec granularity (but still much better than the full second).
Also avoid using this in combination with sleep(), alarm() or select() with a timeout.
As a final remark, remember that Linux is not a real-time OS.  The interval you set will be the minimal delay before the signal is raised, but there can be a substantial additional delay before your code gets to handle the signal.  Once you get in to sub-second intervals, this may not be what you are looking for.
If you have problems using the setitimer() and sigacion() calls, I can post a very simple example that I got running here.
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

786 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question