转自:http://blog.csdn.net/wwwtovvv/article/details/8601528

版权声明:本文为博主原创文章,未经博主允许不得转载。

linux下定时器的使用 -- alarm() & setitimer():

1、alarm
-------------------------------------------
    如果不要求很精确的话,用alarm()和signal()就够了
    unsigned int alarm(unsigned int seconds)
    函数说明: alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。
    返回值:
返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0。
    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、setitimer()
-------------------------------------------
    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。

下面是关于setitimer调用的一个简单示范,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
int sec;
void sigroutine(int signo){
    switch (signo){
        case SIGALRM:
            printf("Catch a signal -- SIGALRM /n");
            signal(SIGALRM, sigroutine);
            break;
        case SIGVTALRM:
            printf("Catch a signal -- SIGVTALRM /n");
            signal(SIGVTALRM, sigroutine);
            break;
    }
    return;
}
int main()
{
    struct itimerval value, ovalue, value2;          //(1)
    sec = 5;
    printf("process id is %d/n", getpid());
    signal(SIGALRM, sigroutine);
    signal(SIGVTALRM, sigroutine);
    value.it_value.tv_sec = 1;
    value.it_value.tv_usec = 0;
    value.it_interval.tv_sec = 1;
    value.it_interval.tv_usec = 0;
   setitimer(ITIMER_REAL, &value, &ovalue);    //(2)
    value2.it_value.tv_sec = 0;
    value2.it_value.tv_usec = 500000;
    value2.it_interval.tv_sec = 0;
    value2.it_interval.tv_usec = 500000;
    setitimer(ITIMER_VIRTUAL, &value2, &ovalue);
    for(;;)
        ;
}
(1) struct itimerval
struct itimerval {
    structtimevalit_interval; /* timer
interval */
    struct timeval it_value;    /* current value */
};
itimerval:      i   --> interval
                val --> value         
   itimerval结构中的it_value是减少的时间,当这个值为0的时候就发出相应的信号了.
然后再将it_value设置为it_interval值.
(2) setitimer()
    setitimer()为其所在进程设置一个定时器,如果itimerval.it_interval不为0(it_interval的两个域都不为0),则该定时器将持续有效(每隔一段时间就会发送一个信号)
    注意:Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,因此,把那些建立在早期机制上的信号叫做"不可靠信号",信号值小于SIGRTMIN(SIGRTMIN=32,SIGRTMAX=63)的信号都是不可靠信号。这就是"不可靠信号"的来源。它的主要问题是:进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。

***********************************

Linux下如何实现秒以下精确定时与休眠

linux中提供的休眠函数是sleep和alarm,但是他们仅仅提供以秒为单位的休眠,这中休眠有些进程显然太长了,那么怎样才能使进程以更小的时间分辨率休眠呢?

我知道的方法有2种,下面就做分别介绍。

第一种方法是使用定时器,Linux提供的定时器函数是:

int  setitimer(int which, const struct itimerval *value, struct

itimerval *ovalue);

which指定那种定时器。Linux提供3种定时器:

TIMER_REAL:
准确定时器,超时会发出SIGALRM信号;

TIMER_VIRTUAL:
虚拟定时器,只记进程时间,所以会根据进程执行时间而变化,不能实现准确定时,超时发出SIGVTALRM信号;

TIMER_PROF:
梗概计时器,它会根据进程时间和系统时间而变化,不能实现准确定时,超时发出SIGPROF信号;

在进程中应该捕捉所设定时器会发出的信号,因为进程收到定时器超时发出的信号后,默认动作是终止。

value是设置定时器时间,相关结构如下:

struct itimerval {
      struct timeval it_interval;
      struct timeval it_value; 
 };
 struct timeval {
      long tv_sec;        
      long tv_usec;
 };

it_interval指定间隔时间,it_value指定初始定时时间。如果只指定it_value,就是实现一次定时;如果同时指定
it_interval,则超时后,系统会重新初始化it_value为it_interval,实现重复定时;两者都清零,则会清除定时器。

tv_sec提供秒级精度,tv_usec提供微秒级精度,以值大的为先,注意1s
= 1000000ms。

ovalue用来保存先前的值,常设为NULL。

如果是以setitimer提供的定时器来休眠,只需阻塞等待定时器信号就可以了。

第二种方法是使用select来提供精确定时和休眠:

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
       struct timeval *timeout);

n指监视的文件描述符范围,通常设为所要select的fd+1,readfds,writefds和exceptfds分别是读,写和异常文件描述符集,timeout为超时时间。

可能用到的关于文件描述符集操作的宏有:

FD_CLR(int fd, fd_set *set);   
清除fd
 FD_ISSET(int fd, fd_set *set);  测试fd是否设置
 FD_SET(int fd, fd_set *set);     设置fd
 FD_ZERO(fd_set *set);             清空描述符集

我们此时用不到这些宏,因为我们并不关心文件描述符的状态,我们关心的是select超时。所以我们需要把readfds,writefds和exceptfds都设为NULL,只指定timeout时间就行了。至于n我们可以不关心,所以你可以把它设为任何非负值。实现代码如下:

int msSleep(long ms) {

struct timeval tv;

tv.tv_sec = 0;

tv.tv_usec = ms;

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

}

呵呵,怎么样,是不是很简单?

结语:

setitimer和select都能实现进程的精确休眠,本文分别对他们进行了简单介绍,并给出了一个简单的给予select的实现。我不推荐使用
setitimer,因为一者Linux系统提供的timer有限(每个进程至多能设3个不同类型的timer),再者ssetitimer实现起来没有
select简单。

Linux应用层的定时器Timer使用详解【转】的更多相关文章

  1. Linux中/proc目录下文件详解

    转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...

  2. Linux中/proc目录下文件详解(转贴)

      转载:http://www.sudu.cn/info/index.php?op=article&id=302529   Linux中/proc目录下文件详解(一) 声明:可以自由转载本文, ...

  3. (转)Linux 开机引导和启动过程详解

    Linux 开机引导和启动过程详解 编译自:https://opensource.com/article/17/2/linux-boot-and-startup作者: David Both 原创:LC ...

  4. 【Linux学习】Linux下用户组、文件权限详解

    原文地址:http://www.cnblogs.com/123-/p/4189072.html Linux下用户组.文件权限详解 用户组 在linux中的每个用户必须属于一个组,不能独立于组外.在li ...

  5. LINUX的磁盘管理du命令详解

    LINUX的磁盘管理du命令详解 du(disk usage)命令可以计算文件或目录所占的磁盘空间.没有指定任何选项时, 它会测量当前工作目录与其所有子目录,分别显示各个目录所占的快数,最后才显示工作 ...

  6. linux sort,uniq,cut,wc命令详解

    linux sort,uniq,cut,wc命令详解 sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些 ...

  7. linux mount命令参数及用法详解

    linux mount命令参数及用法详解 非原创,主要来自 http://www.360doc.com/content/13/0608/14/12600778_291501907.shtml. htt ...

  8. 【转】linux expr命令参数及用法详解

    在抓包过程中,查看某个设定时间内,数据上下行多少,用命令expr 计算! --------------------------------------------------------------- ...

  9. Oracle 11g客户端在Linux系统上的配置步骤详解

    Oracle 11g客户端在Linux系统上的配置步骤详解 2011-07-26 10:47 newhappy2008 CSDN博客 字号:T | T 本文我们主要介绍了Oracle 11g客户端在L ...

随机推荐

  1. JS中调用android和ios系统手机打开相机并可选择相册功能

    编写不易,如有转载,请声明出处: 梦回河口:http://blog.csdn.net/zxc514257857/article/details/57626154 实现android手机打开相机选择相册 ...

  2. Android面试收集录11 Window+Activity+DecorView+ViewRoot之间的关系

    一.职能简介 Activity Activity并不负责视图控制,它只是控制生命周期和处理事件.真正控制视图的是Window.一个Activity包含了一个Window,Window才是真正代表一个窗 ...

  3. P1297 网线切割

    P1297 网线切割 题目描述 Wonderland居民决定举行一届地区性程序设计大赛.仲裁委员会志愿负责这次赛事并且保证会组织一次有史以来最公正的比赛.为此,所有参赛者的电脑和网络中心会以星状网络连 ...

  4. Android 支付宝H5 没有回调

    今天测试反馈问题,说,手机上没有安装支付宝的,调用支付宝支付之后,没有回调.不提示成功也不提示失败. 我自己试了半天也都是没有问题 .后来终于可以试出来了. 发现原来是,清单里面注册的Activity ...

  5. 做出一个SwitchButton的效果,并详细学习一下onDraw(Canvas canvas)方法的使用

    代码的灵感和原理主要来自于android自定义开关控件-SlideSwitch http://blog.csdn.net/singwhatiwanna/article/details/9254309这 ...

  6. 《Cracking the Coding Interview》——第16章:线程与锁——题目4

    2014-04-27 20:06 题目:设计一个类,只有在不产生死锁的时候才分配资源. 解法:不太清楚这个题是要分配何种资源,以何种形式?所以没能动手写个可运行的代码,只是闲扯了几句理论分析. 代码: ...

  7. USACO Section1.4 Mother's Milk 解题报告

    milk3解题报告 —— icedream61 博客园(转载请注明出处)---------------------------------------------------------------- ...

  8. 【Deep Learning】林轩田机器学习技法

    这节课的题目是Deep learning,个人以为说的跟Deep learning比较浅,跟autoencoder和PCA这块内容比较紧密. 林介绍了deep learning近年来受到了很大的关注: ...

  9. 嗯,ACM按照这个一步一步来。

        转一个搞ACM需要的掌握的算法.   要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来. 适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红, 发挥 ...

  10. 【转载】Unity3D研究院transform.parent = parent坐标就乱了

    昨天有朋友问我了一个问题,它将Hierarchy视图里的某个子节点下的GameObject拷贝到另外一个对象的子节点下面,他使用的方法就是 transform.parent = parent 但是拷贝 ...