1.alarm

alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void sigalrm_fn(int sig)
{
    printf("alarm!\n");
    alarm(2);
    return;
}
int main(void)
{
    signal(SIGALRM, sigalrm_fn);
    alarm(1);
    while(1) pause();
}

2.alarm定时器,但是只能精确到秒,然而我们如果需要用到更精准的怎么办?

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));
 setitimer()比alarm功能强大,支持3种类型的定时器:
    ITIMER_REAL :     以系统真实的时间来计算,它送出SIGALRM信号。
    ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
    ITIMER_PROF :     以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。
    setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。
    setitimer()调用成功返回0,否则返回-1。

#include <stdio.h>    // for printf()  

#include <unistd.h>   // for pause()  

#include <signal.h>   // for signal()  

#include <string.h>   // for memset()  

#include <sys/time.h> // struct itimeral. setitimer()  

void printMsg(int);  

int main() {  

  // Get system call result to determine successful or failed  

  int res = ;  

  // Register printMsg to SIGALRM  

  signal(SIGALRM, printMsg);  

  struct itimerval tick;  

  // Initialize struct  

  memset(&tick, , sizeof(tick));  

  // Timeout to run function first time  

  tick.it_value.tv_sec = ;  // sec  

  tick.it_value.tv_usec = ; // micro sec.  

  // Interval time to run function  

  tick.it_interval.tv_sec = ;  

  tick.it_interval.tv_usec = ;  

  // Set timer, ITIMER_REAL : real-time to decrease timer,  

  //                          send SIGALRM when timeout  

  res = setitimer(ITIMER_REAL, &tick, NULL);  

  if (res) {  

    printf("Set timer failed!!/n");  

  }  

  // Always sleep to catch SIGALRM signal  

  while() {  

    pause();  

  }  

  return ;    

}  

void printMsg(int num) {  

  printf("%s","Hello World!!\n");  

}  

setitimer不会引起线程的阻塞、也不会引起线程的切换动作,就是简单的启动一个定时器,开始定时,而且这种定时应该是基于内核的,(windwos的settimer是基于一种消息的模型);setitimer虽然有三种类型ITIMER_REAL,ITIMER_VIRTUAL ITIMER_PROF,但是在同一时间同一进程,一种类型的只能有1个setitimer;
如果我们需要多个定时器怎么办?

[code=C/C++]
#include<stdio.h>   
#include<stdlib.h>   
#include<time.h>   
#include<sys/time.h>   
#include<errno.h>   
#include<string.h>   
#include<unistd.h>   
#include<sys/types.h>   
#include<sys/select.h>   
  
  
int main(int argc, char **argv)  
{  
    unsigned int nTimeTestSec = 0;  
    unsigned int nTimeTest = 0;  
    struct timeval tvBegin;  
    struct timeval tvNow;  
    int ret = 0;  
    unsigned int nDelay = 0;  
    struct timeval tv;  
    int fd = 1;  
    int i = 0;  
    struct timespec req;  
  
    unsigned int delay[20] =   
        {500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0};  
    int nReduce = 0; //误差   
  
    fprintf(stderr, "%19s%12s%12s%12s\n", "fuction", "time(usec)", "realtime", "reduce");  
    fprintf(stderr, "----------------------------------------------------\n");  
    for (i = 0; i < 20; i++)  
    {  
        if (delay[i] <= 0)  
            break;  
        nDelay = delay[i];  
        //test sleep   
        gettimeofday(&tvBegin, NULL);  
        ret = usleep(nDelay);  
        if(ret == -1)  
        {  
            fprintf(stderr, "usleep error, errno=%d [%s]\n", errno, strerror(errno));  
        }  
        gettimeofday(&tvNow, NULL);  
        nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
        nReduce = nTimeTest - nDelay;  
  
         fprintf (stderr, "\t usleep       %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  
         //test nanosleep   
         req.tv_sec = nDelay/1000000;  
         req.tv_nsec = (nDelay%1000000) * 1000;  
  
         gettimeofday(&tvBegin, NULL);  
         ret = nanosleep(&req, NULL);  
         if (-1 == ret)  
         {  
            fprintf (stderr, "\t nanousleep   %8u   not support\n", nDelay);  
         }  
         gettimeofday(&tvNow, NULL);  
         nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
         nReduce = nTimeTest - nDelay;  
         fprintf (stderr, "\t nanosleep    %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  
         //test select   
         tv.tv_sec = 0;  
         tv.tv_usec = nDelay;  
  
         gettimeofday(&tvBegin, NULL);  
         ret = select(0, NULL, NULL, NULL, &tv);  
         if (-1 == ret)  
         {  
            fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));  
         }  
  
         gettimeofday(&tvNow, NULL);  
         nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
         nReduce = nTimeTest - nDelay;  
         fprintf (stderr, "\t select       %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  
         //pselcet   
         req.tv_sec = nDelay/1000000;  
         req.tv_nsec = (nDelay%1000000) * 1000;  
  
         gettimeofday(&tvBegin, NULL);  
         ret = pselect(0, NULL, NULL, NULL, &req, NULL);  
         if (-1 == ret)  
         {  
            fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));  
         }  
  
         gettimeofday(&tvNow, NULL);  
         nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
         nReduce = nTimeTest - nDelay;  
         fprintf (stderr, "\t pselect      %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  
         fprintf (stderr, "--------------------------------\n");  
  
    }  
      
    return 0;  
}

[/code]

int msSleep(long ms) {

struct timeval tv;

tv.tv_sec = 0;

tv.tv_usec = ms;

return select(0, NULL, NULL, NULL, &tv);

}

上面这段代码作者有这样的话
“老大建议我们在对精度要求较高的情况下使用select()作为定时器,最大的好处就是不会影响信号处理线程安全,而且精度能得到保证。在这个实验中,当时间延时时间较长时,select和pselect表现较差,当时间小于1毫秒时,他们的精确度便提高了,表现与usleep、nanosleep不相上下,有时精度甚至超过后者。

查了下上面4个函数,select,和sleep是可重入函数,在使用的时候会引起线程的切换;所以有“不会影响信号处理线程安全”而usleep,nanosleep,不可重入函数,程序是在暂停状态,也就是不能线程切换;但是不知道setitimer会不会记时;

select定时器:

在编写程序时,我们经常会用到定时器。首先看看select函数原型如下:

复制代码代码如下:
int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

参数说明:
slect的第一个参数nfds为fdset集合中最大描述符值加1,fdset是一个位数组,其大小限制为__FD_SETSIZE(1024),位数组的每一位代表其对应的描述符是否需要被检查。
select的第二三四个参数表示需要关注读、写、错误事件的文件描述符位数组,这些参数既是输入参数也是输出参数,可能会被内核修改用于标示哪些描述符上发生了关注的事件。所以每次调用select前都需重新初始化fdset。
timeout参数为超时时间,该结构会被内核修改,其值为超时剩余的时间。
利用select实现定时器,需要利用其timeout参数,注意到:
 1)select函数使用了一个结构体timeval作为其参数。
 2)select函数会更新timeval的值,timeval保持的值为剩余时间。
如果我们指定了参数timeval的值,而将其他参数都置为0或者NULL,那么在时间耗尽后,select函数便返回,基于这一点,我们可以利用select实现精确定时。
timeval的结构如下:

复制代码代码如下:
struct timeval{
long tv_sec;/*secons*
long tv_usec;/*microseconds*/
}

我们可以看出其精确到microseconds也即微妙。
一、秒级定时器

复制代码代码如下:
void seconds_sleep(unsigned seconds){
    struct timeval tv;
    tv.tv_sec=seconds;
    tv.tv_usec=0;
    int err;
    do{
       err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);
}

二、毫秒级别定时器

复制代码代码如下:
void milliseconds_sleep(unsigned long mSec){
    struct timeval tv;
    tv.tv_sec=mSec/1000;
    tv.tv_usec=(mSec%1000)*1000;
    int err;
    do{
       err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);
}

三、微妙级别定时器

复制代码代码如下:
void microseconds_sleep(unsigned long uSec){
    struct timeval tv;
    tv.tv_sec=uSec/1000000;
    tv.tv_usec=uSec%1000000;
    int err;
    do{
        err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);
}

现在我们来编写几行代码看看定时效果吧。

复制代码代码如下:
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
int main()
{
    int i;
    for(i=0;i<5;++i){
    printf("%d\n",i);
    //seconds_sleep(1);
    //milliseconds_sleep(1500);
    microseconds_sleep(1900000);
    }
}

注:timeval结构体中虽然指定了一个微妙级别的分辨率,但内核支持的分别率往往没有这么高,很多unix内核将超时值向上舍入成10ms的倍数。此外,加上内核调度延时现象,即定时器时间到后,内核还需要花一定时间调度相应进程的运行。因此,定时器的精度,最终还是由内核支持的分别率决定。

linux下定时器的实现(select+线程)

更好的计时器类实现:LINUX RTC机制实现计时器类
      很多时候需要在LINUX下用到定时器,但像setitimer()和alarm()这样的定时器有时会和sleep()函数发生冲突,这样就给编程带来了很大的困难。
    写了一个定时器的类,使用select进行精确定时。而且可以在系统中创建不限数量的定时器,且互不干扰。类的内部采用线程实现。即线程+select。代码如下:

CTimer.h:
/*
* CTimer.h
*
* Created on: 2009-7-13
*      Author: DEAN
*/

//////////////////////////////////////////////////////////////////////////
// This class provide a timer to finish some works.
// Call SetTimer() to set the timer_interval. Call StartTimer()
// to enable it and call StopTimer() to stop it.
// The work you want to do should be written on OnTimer
// function.
//////////////////////////////////////////////////////////////////////////

#ifndef CTIMER_H_
#define CTIMER_H_

#include <pthread.h>
#include <sys/time.h>

class CTimer
{
private:
    pthread_t thread_timer;                                            //用于声明线程ID   sizeof(pthread_t)=4;
    long m_second, m_microsecond;
    static void *OnTimer_stub(void *p)
    {
        (static_cast<CTimer*>(p))->thread_proc();       //static_cast < type-id > ( expression )  该运算符把expression转换为type-id类型;
    }
    void thread_proc();                                                   //
    void OnTimer();
public:
    CTimer();
    CTimer(long second, long microsecond);
    virtual ~CTimer();
    void SetTimer(long second,long microsecond);
    void StartTimer();
    void StopTimer();
};
#endif /* CTIMER_H_ */

CTimer.cpp:
/*
* CTimer.cpp
*
* Created on: 2009-7-13
*      Author: DEAN
*/

#include "CTimer.h"
#include <iostream>
#include <sys/select.h>
#include <time.h>
#include <pthread.h>

using namespace std;
//////////////////////////public methods//////////////////////////
CTimer::CTimer():
    m_second(0), m_microsecond(0)
{
}

CTimer::CTimer(long second, long microsecond) :
    m_second(second), m_microsecond(microsecond)
{
}

CTimer::~CTimer()
{
}

void CTimer::SetTimer(long second, long microsecond)
{
    m_second = second;
    m_microsecond = microsecond;
}

void CTimer::StartTimer()
{
    pthread_create(&thread_timer, NULL, OnTimer_stub, this);
}

void CTimer::StopTimer()
{
    pthread_cancel(thread_timer);
    pthread_join(thread_timer, NULL); //wait the thread stopped
}

//////////////////////////private methods//////////////////////////
void CTimer::thread_proc()
{
    while (true)
    {
        OnTimer();
        pthread_testcancel();
        struct timeval tempval;
        tempval.tv_sec = m_second;
        tempval.tv_usec = m_microsecond;
        select(0, NULL, NULL, NULL, &tempval);
    }
}

void CTimer::OnTimer()
{
    cout<<"Timer once..."<<endl;
}

示例代码main.cpp:
/*
* main.cpp
*
* Created on: 2009-7-19
*      Author: DEAN
*/

#include <iostream>
#include "CTimer.h"

using namespace std;

int main()
{
    CTimer t1(1,0),t2(1,0);    //构造函数,设两个定时器,以1秒为触发时间。参数1是秒,参数2是微秒。
    t1.StartTimer();
    t2.StartTimer();
    sleep(10);
    return 0;
}

使用的话其实很简单,只要写一下OnTimer()函数的内容就行了,定时器会在每个定时器触发时调用此函数。里面用到的一个点是使用类的成员函数作为线程体的执行函数,需要进行一下静态类型转换。在上面已标出:
    static void *OnTimer_stub(void *p)
    {
        (static_cast<CTimer*>(p))->thread_proc();
    }
    有了这个类以后,使用定时器就方便多了:-

在LINUX中经常要使用计时器,而在LINUX环境下使用计时器不像WINDOWS环境下那样一个SETTIMER()方便,主要有三种方式:使用SLEEP/USLEEP+单独线程;SETITMER加处理信号SIGALRM,或者是RTC机制。这里我讲到的是使用RTC机制实现计时器类。这种方法最为优越,它与传统意义上的SLEEP和SIGALRM信号是分离的,它的运行不受SLEEP的影响,而像SETITMER等都会受到SLEEP的影响,因为它们使用的是同一时钟。
    以前用select实现的计时器类(http://hi.baidu.com/susdisk/blog/item/03f70d35e8e2e182a61e1288.html)其实并不是真正的计时器,它是一个循环,只是在处理完一次ONTIMER()事件后停下了一秒,然后再接着一次ONTIMER(),这其实并不是真正的计时器。真正的计时器应该是不管是否在处理ONTIMER()事件,它都会触发。
    RTC(real-time clock)。现在可以使用LINUX下的RTC机制来编写计时器类,这个类是完全意义上的计时器,经过测试,也基本不占用cpu时间,因为它采用的是底层的硬件时钟,rtc的文档中说的很明白,它与系统时钟最大的区别在于即使它在机器耗能非常低的情况下,也会触发此时钟信号。它也与SLEEP、SETITIMER等函数是完全独立的,就是说,使用这个计时器类,你依然可以使用各种SLEEP函数等,互不影响,这一点我觉得是最重要的。

参考:

http://www.cnblogs.com/processakai/archive/2012/04/11/2442294.html

http://blog.csdn.net/lxmky/article/details/7669296

Linux定时器 使用的更多相关文章

  1. linux定时器用法

    linux定时器  原文出自http://www.cnblogs.com/processakai/archive/2012/04/11/2442294.html 今天看书看到了关于alarm的一些用法 ...

  2. linux定时器crontab

    linux定时器crontab用法: 1.基本格式 : * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示 ...

  3. Linux 定时器应用【转】

    Linux 定时器应用 实验目的 阅读 Linux 相关源代码,学习 Linux 系统中的时钟和定时器原理,即,ITIMER_REAL实时计数,ITIMER_VIRTUAL 统计进程在用户模式执行的时 ...

  4. 4412 Linux定时器

    一.Linux定时器基础知识 1.1 定时器的使用范围 延后执行某个操作,定时查询某个状态:前提是对时间要求不高的地方 1.2 内核时间概念 Hz:(系统时钟通过CONFIG_HZ来设置,范围是100 ...

  5. linux定时器(crontab)实例

    linux实验示例----实现每2分钟将“/etc”下面的文件打包存储到“/usr/lobal”目录下 ·Step1:编辑当前用户的crontab并保存终端输入:>crontab -u root ...

  6. Linux定时器相关源码分析

    Linux的定时器使用时间轮算法.数据结构不难理解,核心数据结构与散列表及其相似,甚至可以说,就是散列表.事实上,理解其散列表的本质,有助于对相关操作的理解. 数据结构 这里先列出一些宏,稍后解释: ...

  7. Smart210学习记录-----linux定时器

    1.内核定时器: Linux 内核所提供的用于操作定时器的数据结构和函数如下: (1) timer_list 在 Linux 内核中,timer_list 结构体的一个实例对应一个定时器 1 stru ...

  8. linux 定时器编程实例(完善中).....

    最近在写linux 下的定时器编程实验,测试发现 usleep函数在 x86 架构下的定时还是比较准确的,在arm9下 就不太准了. 今天用linux 下的setitimer()函数进行了定时 器的测 ...

  9. linux定时器HZ和Jiffies

    1.linux HZ Linux核心几个重要跟时间有关的名词或变数,以下将介绍HZ.tick与jiffies. HZ Linux核心每隔固定周期会发出timer interrupt (IRQ 0),H ...

  10. linux定时器

    我们常常有设置系统在某一时间执行相应动作的需求,比如设置电脑什么时候自动锁屏,什么时候自动关机,设置应用程序什么时候自动运行,什么时候自动退出.这些与时间相关的功能,都需要依靠操作系统中的定时器来实现 ...

随机推荐

  1. Python-Scrapy创建第一个项目

    创建项目 在开始爬取之前,您必须创建一个新的Scrapy项目.进入您打算存储代码的目录中,运行下列命令: scrapy startproject tutorial 1 该命令行将会创建包含下列内容的t ...

  2. JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)

    性能分析工具jstatjmapjhatjstack 前提概要:         JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jsta ...

  3. 简述基于Struts框架Web应用的工作流程

    简述基于Struts框架Web应用的工作流程 解答:在web应用启动时就会加载初始化ActionServlet,ActionServlet从struts-config.xml文件中读取配置信息,把它们 ...

  4. 【C++自我精讲】基础系列三 重载

    [C++自我精讲]基础系列三 重载 0 前言 分二部分:函数重载,操作符重载. 1 函数重载 函数重载:指在同一名字空间中,函数名称相同,参数类型.顺序或数量不同的一类函数,同一函数名的函数能完成不同 ...

  5. [转]使用TeamCity对项目进行可持续集成管理(一)

    一.可持续集成管理 持续集成,CI:即Continuous integration. 可持续集成的概念是基于团队(小组)协作开发而提出来的,为了提高团队开发效率与降低集成风险(早发现,早解决.晚发现, ...

  6. shell基础(三)

    函数 1.可以带function fun() 定义,也可以直接fun() 定义,不带任何参数: 2.参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值: 3.必须 ...

  7. py-faster-rcnn 训练自己的数据

    转载:http://blog.csdn.net/sinat_30071459/article/details/51332084  Faster-RCNN+ZF用自己的数据集训练模型(Python版本) ...

  8. 主干(trunk)、分支(branch )、标记(tag) 用法示例 + 图解

    以svn为例,git的master相当于trunk,dev分支相当于branches --------------------------------------------------------- ...

  9. AngularJS 讲解,二 模块

    AngularJS允许我们使用angular.module()方法来声明模块,这个方法能够接受两个参数,第一个是模块的名称,第二个是依赖列表,也就是可以被注入到模块中的对象列表. angular.mo ...

  10. 报错 findMergedAnnotation activemq

    springmvc 集成activemq引入activemq-all-5.14.4有冲突 springmvc 4.2.9集成activemq-5.14.4时报错,错误信息如下 NoSuchMethod ...