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

今天看书看到了关于alarm的一些用法,自己有在网上找了些资料看了下;
1。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定时器,但是只能精确到秒,然而我们如果需要用到更精准的怎么办?
经过群里的大牛知道,看了下可以用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信号:[code=C/C++]
#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(;;)
        ;
}
setitimer不会引起线程的阻塞、也不会引起线程的切换动作,就是简单的启动一个定时器,开始定时,而且这种定时应该是基于内核的,(windwos的settimer是基于一种消息的模型);setitimer虽然有三种类型ITIMER_REAL,ITIMER_VIRTUAL
ITIMER_PROF,但是在同一时间同一进程,一种类型的只能有1个setitimer;
如果我们需要多个定时器怎么办?
3.

[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会不会记时;

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. 剑指offer:二叉树的深度

    题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 解题思路: 这道题也是递归的思路,比较简单. 做的过程中遇到的一个 ...

  2. Daily Scrum 10.20

    今天进行了团队第一次scrum meeting,在这次会议中,我们针对NABC模型以及开发前期的工作进行了探讨. 第一次会议 主要内容如下: 为了大家接下来几周的开发效率,需要共同商量团队的一些规则 ...

  3. Do in SDN

    Do in SDN 书籍 <深度解析SDN 利益.战略.战术.实践> 张卫锋 <重构网络-SDN构架与实现>杨泽卫.李呈 <软件定义网络核心原理与应用实践> 黄韬. ...

  4. 老李的blog使用日记(2)

    寥寥数语结束一个不曾期待的遇见,可还是剧情不会这样结束,他也会在我的时间里注册自己的专属账号,无论什么时候,他会时而需要被注视着,为了达到目的,即使不择手段,只为一次擦肩而过的邂逅,极短的一段时间,相 ...

  5. 【Leetcode】378. Kth Smallest Element in a Sorted Matrix

    Question: Given a n x n matrix where each of the rows and columns are sorted in ascending order, fin ...

  6. LDAP的前世今生

    上世界80年代,就有了LDAP的雏形. 我接触到最早的Windows系列的服务器,是Windows2000 Professional版本里可以加入ActiveDirectory,后来从Windows2 ...

  7. Mac OS X使用简介

    一.OS X 版本以大型猫科动物命名 10.0   猎豹(Cheetah) 10.1   美洲狮(Puma) 10.2   美洲虎(Jaguar) 10.3   黑豹(Panther) 10.4   ...

  8. 【题解】 bzoj1503: [NOI2004]郁闷的出纳员 (Splay)

    bzoj1503,懒得复制,戳我戳我 Solution: 我知不知道我是那根筋抽了突然来做splay,调了起码\(3h+\),到第二天才改出来(我好菜啊),当做训练调错吧 一个裸的splay,没啥好说 ...

  9. emoji表情存储到数据库的方法

    方案1:修改数据库编码 为什么我们设置表的的字符类型为utf8却不能存放emoji呢?原来utf8可能是2或3或4个字节,而mysql的utf8是3个字节,存放一个emoji是需要4个字节的,自然不够 ...

  10. 使用swagger2配置springboot时出现的问题

    这个问题踩了几次坑了,这次又遇到了,不记录一下看来是不长记性了: 测试普通的增删改查的时候,发现删除和查询是对的,可是增加和更新却数据绑定不到controller的参数上面去. 因为是自定义的实体类, ...