开发者

Best way to do a timer in UNIX

I always notice people have different reactions to different ways of creating a timer in UNIX.

I know a few different ways that I could make an event execute every X seconds within UNIX:

  • you can do a polling thread - pthread_t with sleeps;
  • you can do a select() with a timeout;
  • and I guess you can use the OS in a few other ways.

Can someone provide some sample code with the "best" or most efficient way to do a timer and a description of why it is th开发者_运维百科e best? I'd like to use the most efficient mechanism for this but I'm not sure which one it is!

For our purposes, just pretend you're printing "Hello World!" once every 10 seconds.

NOTE: I don't have TR1/Boost/etc. on this system, so please keep it to straight-up C/C++ and UNIX system calls. Sorry for not mentioning that the first time :)


It depends on what you are wanting to do. A simple sleep will suffice for your trivial example of waiting 10 sec between "Hello"s since you might as well suspend your current thread until your time is up.

Things get more complicated if your thread is actually doing something while you are waiting. If you are responding to incoming connections, you will already be using select in such a case a timeout to your select statement makes the most sense for your housekeeping.

If you are processing stuff in a tight loop, you might regularly poll a start time to see if your 10 seconds are up.

alarm with an appropriate signal handler will work as well but there are severe limits to what you can do in a signal handler. Most of the time, it involved setting a flag that will need to be polled every so often.

In a nutshell, it comes down to how your thread is processing events.


Use an event-driven loop like Boost.Asio

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class Timer
{
public:
    Timer(
            boost::asio::io_service& io_service
         ) :
        _impl( io_service )
    {
        this->wait();
    }

private:
    void wait()
    {
        _impl.expires_from_now( boost::posix_time::seconds(10) );
        _impl.async_wait(
                boost::bind(
                    &Timer::handler,
                    this,
                    _1
                    )
                );
    }

    void handler(
            const boost::system::error_code& error
            )
    {
        if ( error ) {
            std::cerr << "could not wait: " << boost::system::system_error(error).what() << std::endl;
            return;
        }

        std::cout << "Hello World!" << std::endl;

        this->wait();
    }

private:
    boost::asio::deadline_timer _impl;
};

int main()
{
    boost::asio::io_service io;

    Timer t( io );

    io.run();

    return 0;
}

build & run:

stackoverflow samm$ ./a.out
Hello World!
Hello World!
Hello World!
^C
stackoverflow samm$ 


If your program is already threaded, then using a poll thread is simple and effective.

If your program is not already threaded, then it gets trickier. Can you use a separate process to do the job? If so, then using multi-processing instead of multi-threading.

If you cannot use an autonomous thread of control (process or thread), then it depends on how your program is organized, which is why there are many preferred alternatives (they are preferred for different circumstances). It also depends on the accuracy of timing that you require. With multi-second gaps and no hard real-time response requirement, you might use an alarm and the SIGALRM handler can set a flag and your main processing loop can monitor the flag at convenient, sensible points and do the activity. This is somewhat messy (because signals are messy), but without a more detailed description of your requirements and constraints, it is hard to know what else to suggest.

So, in summary, there isn't a single universally best solution because different programs are written in different styles and under different constraints.


The choices of how to do a timer vary in ease of use, portability, accuracy, ugliness (global state/signals), and suitability for realtime applications. Personally, for the best of all worlds, I would recommend rolling your own timer with a thread, and using clock_nanosleep with the TIMER_ABSTIME flag and the CLOCK_MONOTONIC clock source. This way you can avoid accumulated error and discontinuities from setting the system time, and you can count overruns yourself. In theory, POSIX timer_create with SIGEV_THREAD delivery should give you the same properties, but the glibc implementation is really bad and cannot guarantee that it will not lose timer expiration events under heavy load.


sleep() is the easiest way. usleep() exists on some variants. If you want sub-second accuracy, select(NULL, NULL, NULL &timeout) is the most portable, unless you write your own OS-specific routines. The select() method has the advantage that timeout is updated to reflect the amount of time remaining if the call was interrupted by a signal. You can resume the wait if needed.

Really, all of the methods are equivalent; the OS stops scheduling the thread for the timeout period.

The SIGALARM method suggested by Blagovestus is (somewhat) unportable, even though it should work on Linux.


This is a late response, but I wanted to add my implementation of a timer. It is a threaded timer, and needs some work, with wrapping up mutexes and pthreads in their own classes (lack of RAII in that respect). It is also not cross platform since it uses the gettimeofday() method.

The code uses a timer that calls on a CallBack object. The entire source can be seen at

http://matthewh.me/playground/browser/branches/C%2B%2B/c%2B%2B_callbacks


If you just have to output "Hello world" once every 10 seconds, I guess sleeps and nanosleeps will do. If your tasks are somehow more critical, you could take a look to RealTime Linux. There (www.ee.nmt.edu/~rison/ee352_fall09/Getting_Started_with_RTLinux.pdf) they put a good guide on that. When using RTLinux you can use pthread_make_periodic_np to make a task periodic, though you'll be the one in charge of making sure that real time conditions are satisfied.


simple way to create a timer in c is to use sleep(time_in_seconds)

sleep(3); // waits for 3 seconds
doSomeJob();

you can also find few more code snippets for time conversations in various languages here(https://unixtimer.com)

if you need control on the timer and need to do customized task based on time, you can use clock() in "#include <time.h>"

int milli_sec = 0, trigger_time = 100; i_trigger = 5; /* trigger_time-> 100ms, i_trigger-> 5ms */
clock_t before = clock();

do {
  /*
   * Do something to busy the CPU just here while you drink a coffee
   * Be sure this code will not take more than `trigger_time` ms
   */

  clock_t difference = clock() - before;
  milli_sec = difference * 1000 / CLOCKS_PER_SEC;
  iterations++;
  if(milli_sec==i_trigger){
    // do something in async
  }
} while ( milli_sec < trigger_time );

printf("Time taken %d seconds %d milliseconds (%d iterations)\n",
  milli_sec/1000, milli_sec%1000, iterations);


  [1]: https://www.unixtimer.com/
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜