`
fp_moon
  • 浏览: 983054 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Linux下时间和定时器

 
阅读更多

http://blog.chinaunix.net/u1/35065/showart_1870601.html
重点读了第三种方法。文章写得很好,加了一点点注释

可参考 http://linux.die.net/man/3/timer_settime
              http://linux.die.net/man/2/setitimer 
              http://opengroup.org/onlinepubs/007908799/xsh/timer_settime.html

---毫秒---微秒---纳秒 (数量级:1000

一、问题的提出
我们开发程序时,经常会遇到时间和定时器的问题,为了更好的使用时间和定时器,现在列举一个一些时间结构体、函数和定时器。

二、解决思路
1.
时间类型
1) time_t
是一个长整型,一般用来表示用1970年以来的秒数。

2)struct timeval有两个成员,一个是秒,一个是微妙。

struct timeval
{             
long tv_sec;        /* seconds */        
long tv_usec;   /* microseconds */  
};

3) struct timespec有两个成员,一个是秒,一个是纳秒。

struct timespec
{
   time_t tv_sec;          /* seconds */
   long    tv_nsec;        /* nanoseconds */
};

4) struct tm是直观意义上的时间表示方法

struct tm
{                  
int     tm_sec;         /* seconds */                   
int     tm_min;         /* minutes */                     
int     tm_hour;        /* hours */                  
int     tm_mday;         /* day of the month */                        
int     tm_mon;         /* month */                    
int     tm_year;        /* year */                  
int     tm_wday;         /* day of the week */                        
int     tm_yday;        /* day in the year */                          
int     tm_isdst;        /* daylight saving time */           
};

5)

     struct timeb
     {
        time_t    time;            //
1970来经过的秒数

        unsigned short millitm; //
毫秒
        short     timezone;        //
时区
        short     dstflag;//
为日光节约时间的修正值,如果为非0代表启用日光节约修正
};

   6)

      struct timezone
{
         int tz_minuteswest;//
和格林尼治时间相差多少分

         int tz_dsttime;//
日光节约时间的状态 
};

   日光节约时间:夏时制。

2.时间函数
1) char *asctime(const struct tm *timeptr)

将时间和日期以字符串格式显示。

2clock_t clock(void)

   取得进程占用cpu的大约时间。

3char *ctime(const time_t *timep)

将时间和日期以字符串格式显示。

4) double difftime(time_t time1, time_t time0)

计算时间time1time0间的差距。

5) int ftime(struct timeb *tp)

   取得目前的时间和日期。

6) int gettimeofday(struct timeval *tv, struct timezone *tz)

   取得目前的时间。

7strcut tm *gmtime(const time_t *timep)

   time_t结构时间转tm结构时间,tmUTC时区。

8) struct tm *localtime(const time_t *timep)

   time_t结构时间转tm结构时间,tm是当地时区。

9time_t mktime(struct tm *timeptr)

   tm结构时间转换为time_t

10) int settimeofday(const struct timeval *tv, const struct timezone *tz)

   设置时间为tv,设置时区为tz

11) size_t strftime(char *s, size_t max, const char *format, const struct tm *tm)

   将参数tm的时间结构依照参数format所指定的字符串格式做转换,转换后的字符串将复制到参数s所指的字符串数组中,该字符串的最大长度为参数max所控制。

12) time_t time(time_t *t)

   取得目前的时间,时间按照UTC

13) void tzset(void)

   从环境变量TZ取得目前当地的时间。

3.延迟函数
主要的延迟函数有:sleep(),usleep(),nanosleep(),select(),pselect().

1) unsigned int sleep(unsigned int seconds)

延时seconds秒。

2) void usleep(int micro_seconds)

延时 micro_seconds微妙

3) int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)

延时的时间为rqtp,如果nansleep被信号中断,且rmtp不为NULL,则rmtp指定的位置上包含的就是剩余时间。

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

如果将readfds, writefds, exceptfds置为NULLtimeout为非零,则延时timeout

5) int pselect(int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec tsptr, const sigset_t *sigmask)

如果将readfds, writefds, exceptfds置为NULLtsptr为非零,则延时tsptr

3.定时器
1) unsigned int alarm(unsigned int seconds)

设置一个定时器,在seconds秒后超时,当定时器超时时,产生SIGALRM信号。如果不忽略或不捕捉此信号,则其默认动作是终止调用该alarm函数的进程,如果设置了SIGALRM信号处理函数,则会执行该信号处理函数。

每个进程只能有一个闹钟时钟。如果在调用alarm时,以前已为该进程设置过闹钟时钟,而且它还没有超时,则将该闹钟时钟的余留值作为本次alarm函数调用的值返回,以前登记的闹钟时钟则被新值代替。

例子:

void sigalrm_fn(int sig)

{

printf("alarm!\n");

alarm(2);

return;

}

 

int main(void)

{

signal(SIGALRM, sigalrm_fn);

alarm(1);

while(1) pause();

}

 

2) POSIX:XSI间隔定时器

int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);

struct itimerval

{
    struct timeval it_interval; /*
计时器重启动的间歇值
*/
    struct timeval it_value;    /*
计时器安装后首先启动的初始值
*/
};

 

   getitimer()用计时器的当前值填写value指向的结构体。
setitimer()
value指向的结构体设为计时器的当前值,如果ovalue不是NULL,将返回计时器原有值。

which:间歇计时器类型,有三种选择:

l         ITIMER_REAL //数值为0,计时器的值实时递减,发送的信号是SIGALRM

l         ITIMER_VIRTUAL //数值为1,进程执行时递减计时器的值(虚拟时间),发送的信号是SIGVTALRM

l         ITIMER_PROF //数值为2,虚拟时间和进程的系统时间递减,发送的信号是SIGPROF

itimerval结构中的it_value是减少的时间,当这个值为0的时候就发出相应的信号了. 然后再将it_value设置为it_interval. 也就是先处理it_value中设置的值,为0后发送信号(根据which来判断发送什么信号),之后都是根据it_interval的值发送信号。若it_valueit_interval都为0,也就没有相应的信号产生了。

alarm()一样,由于信号的限制,POSIX:XSI间隔定时器对于每个进程来说最多只有3个定时器。

例子:

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;

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);

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(;;)

;

}

3)POSIX:TMR间隔定时器

int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)

   进程可以通过调用timer_create()创建特定的定时器,定时器是每个进程自己的,不是在fork时继承的。timer_create的参数clock_id说明定时器是基于哪个时钟的,*timerid装载的是被创建的定时器的IDtimer_create函数创建了定时器,并将他的ID放入timerid指向的位置中。参数evp指定了定时器到期要产生的异步通知。如果evpNULL,那么定时器到期会产生默认的信号,对CLOCK_REALTIMER来说,默认信号就是SIGALRM。对那些定时器到期时要产生除默认信号之外的其它信号的定时器来说,程序必须将evp->sigev_signo设置为期望的信号码。struct sigevent 结构中的成员evp->sigev_notify说明了定时器到期时应该采取的行动。通常,这个成员的值为SIGEV_SIGNAL,这个值说明在定时器到期时,会产生一个信号。程序可以将成员evp->sigev_notify设为SIGEV_NONE来防止定时器到期时产生信号。

 

如果几个定时器产生了同一个信号,处理程序可以用evp->sigev_value来区分是哪个定时器产生了信号。要实现这种功能,程序必须在为信号安装处理程序时,使用struct sigaction的成员sa_flags中的标志符SA_SIGINFO

clock_id的取值为以下:

CLOCK_REALTIME :Systemwide realtime clock.

CLOCK_MONOTONIC:Represents monotonic time. Cannot be set.

CLOCK_PROCESS_CPUTIME_ID :High resolution per-process timer.

CLOCK_THREAD_CPUTIME_ID :Thread-specific timer.

CLOCK_REALTIME_HR :High resolution version of CLOCK_REALTIME.

CLOCK_MONOTONIC_HR :High resolution version of CLOCK_MONOTONIC.

 

struct sigevent

{

int sigev_notify; //notification type

int sigev_signo; //signal number

union sigval   sigev_value; //signal value

void (*sigev_notify_function)(union sigval);

pthread_attr_t *sigev_notify_attributes;

}

union sigval

{

int sival_int; //integer value

void *sival_ptr; //pointer value

}

通过将evp->sigev_notify设定为如下值来定制定时器到期后的行为:

l         SIGEV_SIGNAL: 发送由evp->sigev_sino指定的信号到调用进程,evp->sigev_value的值将被作为siginfo_t结构体中si_value的值。

l         SIGEV_NONE:什么都不做,只提供通过timer_gettimetimer_getoverrun查询超时信息。

l         SIGEV_THREAD: evp->sigev_notification_attributes为线程属性创建一个线程,在新建的线程内部以evp->sigev_value为参数调用evp->sigev_notification_function

 

int timer_delete(timer_t timerid);

删除IDtimeridPOSIX:TMR定时器。

int timer_settime(timer_t timerid,int flags,const struct itimerspec *value,struct itimerspec *ovalue);

struct     itimerspec   
{  
 
       struct     timespec   it_interval; //
定时器周期值
       struct     timespec   it_value;     //
定时器到期值
};  
 

      timer_settime负责启动或停止timer_create创建的定时器。参数flag说明定时器使用的是相对时间还是绝对时间。相对时间与POSIX:XSI定时器使用的策略类似,而绝对时间的精确度更高。参数vaule指向的值来设置timerid指定的定时器。如果ovalue不为NULLtimer_settime就将定时器以前的值放在ovalue指定的位置上。如果定时器正在运行,那么*ovalue的成员it_value非零,并包含了定时器到期之前剩余的时间。

TIMER_ABSTIME表示绝对时间;
如果flag没有设定为TIMER_ABSTIME,则定时器从调用开始在it_value内超时;value->it_value代表计时器第一次超时的时间。
如果设定为TIMER_ABSTIME,该函数表现为时间直到下一次超时被设定为it_value指定的绝对时间和与timerid相联的时钟值的差值。如果已经到了it_value指定的值,那么超时后的处理就会立即执行。

定时器的再装由valueit_interval成员值来设定。



int timer_gettime(timer_t timerid,struct itimerspec *value);

获得一个活动定时器的剩余时间。

int timer_getoverrun(timer_t timerid);

       有可能一个定时器到期了,而同一定时器上一次到期时产生的信号还处于挂起状态。在这种情况下,其中的一个信号可能会丢失。这就是定时器超限。程序可以通过调用timer_getoverrun来确定一个特定的定时器出现这种超限的次数。定时器超限只能发生在同一个定时器产生的信号上。由多个定时器,甚至是那些使用相同的时钟和信号的定时器,所产生的信号都会排队而不会丢失。

例子:

编译方法:

     gcc -o example example.c   -lrt   -lpthread   

那个rt库就是POSIX   realtime   extension的库。

 

#include   <stdio.h>  

#include   <time.h>  

#include   <signal.h>  

#include   <string.h>//不然会出现对memset函数的警告

void  

handle   (union sigval   v)  

{  

      time_t   t;  

      char   p[32];  

 

      time   (&t);  

      strftimep,   sizeof   (p),   "%T",   localtime   (&t));  

      printf("%s   thread   %lu,   val   =   %d,   signal   captured.\n",   p,   pthread_self(), v.sival_int);  

      return;  

}  

   

int create   (int   seconds,   int   id)  

{  

      timer_t   tid;  

      struct   sigevent   se;  

      struct   itimerspec   ts,   ots;  

      memset   (&se,   0,   sizeof   (se));  

      se.sigev_notify   =   SIGEV_THREAD;  

      se.sigev_notify_function   =   handle;  

      se.sigev_value.sival_int   =   id;   //作为handle()的参数

      if   (timer_create   (CLOCK_REALTIME,   &se,   &tid)   <   0)  

          {  

              perror   ("timer_creat");  

              return   -1;  

          }  

      puts   ("timer_create   successfully.");  

      ts.it_value.tv_sec   =   3;  

      ts.it_value.tv_nsec   =   0;  

      ts.it_interval.tv_sec   =   seconds;  

      ts.it_interval.tv_nsec   =   0;  

      if   (timer_settime (tid,   TIMER_ABSTIME,   &ts,   &ots)   <   0)  

          {  

              perror   ("timer_settime");  

              return   -1;  

          }  

      return   0;  

}  

   

int   main   (void)  

{  

      create   (3,   1);  

      create   (5,   2);  

      for   (;;)  

          {  

              sleep   (10);  

          }  

}

三、总结
Linux
下定时器主要使用上面介绍的三种定时器。

 

分享到:
评论

相关推荐

    linux下多定时器+线程池的实现(经典)

    //linux只允许单进程拥有一个定时器,因此在linux下的单进程中要使用多个定时器,则需要自己维护管理 // //这个实现允许用户使用多个自定义的定时器,每个自定义的定时器将周期地被触发直到其被删除。实现的主要思路...

    Linux设备驱动之定时器

    ### Linux设备驱动中的定时器机制 #### 一、引言 在Linux内核及设备驱动开发中,定时器是十分重要的...定时器在Linux内核和设备驱动程序中扮演着非常重要的角色,理解其工作原理对于深入学习Linux内核具有重要意义。

    Linux下C语言 定时器

    本节我们将深入探讨Linux环境下如何使用C语言创建基于红黑树(Red-Black Tree)的多线程定时器,以及如何设置定时回调函数,其定时单位精确到毫秒。 首先,我们需要了解什么是定时器。定时器是一种机制,它可以在...

    RT-Linux的细粒度定时器的实现方法.pdf

    3. **可编程能力**:为了适应不同实时任务对时间参数的不同需求,RT-Linux的定时器允许在不同模式下进行编程,增强了系统的灵活性和适应性。 在实现这一改进的过程中,作者分析了x86架构的硬件时钟原理,这是构建高...

    linux应用程序中定时器的应用

    在Linux操作系统中,定时器(Timer)是一种非常重要的工具,它允许程序在特定时间间隔后执行某些操作。在软件开发中,特别是在系统级编程或服务端应用中,定时器的运用广泛,例如心跳检测、任务调度、超时处理等场景...

    Linux系统中内核定时器的应用

    在Linux操作系统中,内核定时器是系统实现各种时间相关功能的关键组件。它们允许程序在特定时间间隔后执行特定操作,而无需持续消耗CPU资源。本文将深入探讨Linux内核定时器的应用及其相关概念。 首先,我们来看一...

    Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现 - DroidPhone的专栏 - 博客频道 - CSDN

    Linux时间子系统中的高精度定时器(High Resolution Timer,简称HRTIMER)是为了解决传统低分辨率定时器精度不足的问题而引入的。在Linux内核2.6.16版本之后,高精度定时器被引入,以提供纳秒级别的定时精度,这在对...

    第9章linux信号与定时器

    通过编写一个程序来注册三个定时器,分别对实际时间、进程使用CPU时间、用户使用CPU时间进行计时,可以深入理解信号与定时器在Linux环境下的应用。这种练习有助于开发者掌握如何在实际项目中使用这些机制,提高程序...

    Linux下实时定时器的实现及应用

    根据给定的文件信息,以下是对“Linux下实时定时器的实现及应用”的详细解析,主要涵盖定时器的实现背景、内核中的时钟管理、延时机制、实时时钟的具体实现及其应用。 ### 实时定时器的实现背景 在嵌入式系统开发...

    linux 多线程安全定时器

    在Linux系统中,多线程编程常常涉及到时间管理和同步,以确保程序的高效与正确运行。`timerfd`和`epoll`是两种常见的机制,它们在处理多线程安全定时器方面各自扮演着重要角色。 `timerfd`是Linux内核2.6.28版本...

    Linux下一种高性能定时器池的实现

    本文提出的“Linux下一种高性能定时器池的实现”正是针对这一问题,它利用时间轮和红黑树的数据结构,结合Linux内核的timerfd机制,设计了一个高效、低延迟的定时器池。 首先,时间轮是一种高效的定时器管理策略,...

    一种简单易用的linux的C语言的定时器接口

    "使用说明.txt"文件很可能是提供详细的使用教程和示例,包括如何初始化定时器、设置定时间隔、注册回调函数、启动和停止定时器等内容。这将帮助开发者快速理解和应用这个接口。 "a_good_timer_driver"文件名暗示它...

    Linux下posix线程实现的定时器

    本篇文章将深入探讨如何在Linux环境下利用pthread库创建和管理定时器,以及它在实际应用中的作用。 POSIX线程库中的定时器主要由`pthread_cond_t`条件变量和`pthread_mutex_t`互斥锁配合使用,实现定时触发回调函数...

    实用的Linux c 定时器代码

    总的来说,CTimer类封装了Linux下的定时器功能,提供了一种方便的方式来在C++项目中实现定时任务,降低了开发者的编程负担,并提高了代码的可复用性。通过理解和使用CTimer,开发者可以更好地掌握Linux系统编程中的...

    linux下自定义定时器的实现

    本文将深入探讨如何在Linux环境下创建、管理和使用应用层的定时器,以及如何通过系统调用来开启定时器。 首先,我们要了解Linux中的定时器类型。主要有两种定时器:实时定时器(Real-Time Timers)和进程定时器...

    基于Linux定时器管理器

    通过合理利用Linux定时器,开发者可以实现高效、精确的任务调度和时间控制。 总结,Linux定时器管理器是操作系统中不可或缺的一部分,它为程序提供了灵活的定时和调度能力。理解和掌握如何添加、删除定时器,以及...

    Zynq-Linux-Timer中断源码加参考文档

    在Linux内核中,存在两种主要类型的定时器:软定时器(software timers)和硬定时器(hardware timers)。软定时器运行在用户空间或内核空间,由软件调度;而硬定时器则基于硬件中断,通常更准确且不受CPU负载影响。...

    Linux定时器代码

    在Linux系统中,定时器是实现程序自动化执行和时间间隔控制的关键组件。它们允许程序员设置一个时间点或间隔,让操作系统在指定的时间后执行特定的任务。在这个“Linux定时器代码”主题中,我们将深入探讨与时间相关...

    linux下定时器实现

    在Linux系统中,定时器是实现程序自动化执行和时间间隔控制的重要工具。本文将深入探讨三种常见的定时器实现方法:最小堆、红黑树以及时间轮,并重点介绍效率最高的时间轮定时器及其应用。 首先,让我们了解最基本...

Global site tag (gtag.js) - Google Analytics