- 浏览: 980364 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
custjcy:
不错,赞一个。尤其是这个,在查找指定目录下,列出所有包含某个字 ...
shell命令的批量修改文件内容 -
qw173795180:
你好,请问Start这个参数怎么使用不了?
视频播放flv player的使用 -
cheeruplc:
xml进行修改之后 刷新请求 不执行 看了你的博文解决 ...
同一页面无法多次使用XmlHttp发起Ajax请求的真实原因--l转 -
dongbiying:
没有想到还有map的概念
js数组的操作及数组与字符串的相互转化 -
wangtuda:
打酱油的~
js中随机排序
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)
将时间和日期以字符串格式显示。
2)clock_t clock(void)
取得进程占用cpu的大约时间。
3)char *ctime(const time_t *timep)
将时间和日期以字符串格式显示。
4) double difftime(time_t time1, time_t time0)
计算时间time1和time0间的差距。
5) int ftime(struct timeb *tp)
取得目前的时间和日期。
6) int gettimeofday(struct timeval *tv, struct timezone *tz)
取得目前的时间。
7)strcut tm *gmtime(const time_t *timep)
time_t结构时间转tm结构时间,tm为UTC时区。
8) struct tm *localtime(const time_t *timep)
将time_t结构时间转tm结构时间,tm是当地时区。
9)time_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置为NULL,timeout为非零,则延时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置为NULL,tsptr为非零,则延时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_value和it_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装载的是被创建的定时器的ID。timer_create函数创建了定时器,并将他的ID放入timerid指向的位置中。参数evp指定了定时器到期要产生的异步通知。如果evp为NULL,那么定时器到期会产生默认的信号,对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_gettime和timer_getoverrun查询超时信息。
l SIGEV_THREAD: 以evp->sigev_notification_attributes为线程属性创建一个线程,在新建的线程内部以evp->sigev_value为参数调用evp->sigev_notification_function。
int timer_delete(timer_t timerid);
删除ID为timerid的POSIX: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不为NULL,timer_settime就将定时器以前的值放在ovalue指定的位置上。如果定时器正在运行,那么*ovalue的成员it_value非零,并包含了定时器到期之前剩余的时间。
TIMER_ABSTIME表示绝对时间;
如果flag没有设定为TIMER_ABSTIME,则定时器从调用开始在it_value内超时;即value->it_value代表计时器第一次超时的时间。
如果设定为TIMER_ABSTIME,该函数表现为时间直到下一次超时被设定为it_value指定的绝对时间和与timerid相联的时钟值的差值。如果已经到了it_value指定的值,那么超时后的处理就会立即执行。
定时器的再装由value的it_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下定时器主要使用上面介绍的三种定时器。
发表评论
-
防火墙实现URL过滤原理
2014-05-08 18:45 4330对于URL过滤:1.HTTP URL过滤 2.https UR ... -
解决webserver在IE下载文件,文件名为乱码问题
2013-12-28 16:26 1413通常使用以下代码就能导出为流的文件,而不是打开文件 w ... -
C实现urlencode&urldecode
2013-12-28 16:20 6003static unsigned char char_to_he ... -
c语言实现urlencode
2013-12-28 16:19 2043#include <stdio.h> #inc ... -
wifidog+authpuppy认证页面的配置
2013-10-29 02:15 3448转自:http://blog.sina.com.cn/s/ ... -
atoi() & itoa()&atol()<oa()函数的实现
2013-05-01 13:53 3064#include "stdio.h" ... -
详解sigaction --转
2013-04-20 03:31 11369详解sigaction 这是挺好理解的,就好比在系 ... -
Linux定时器的使用 --转
2013-04-20 01:13 1455使用定时器的目的无非是为了周期性的执行某一任务,或者是到了 ... -
Linux C 函数参考(日期时间) --转
2013-04-20 00:03 11449Linux C 函数参考(日期时间) 1.1 概述 世 ... -
对(*(volatile unsigned long *)) 的理解
2013-03-20 15:10 1538对(*(volatile unsign ... -
Linux内核模块概述 --转
2013-01-08 10:43 2448Linux内核模块概述 . Linux 内 ... -
linux上搭建pppoe-server
2012-12-28 15:53 8881记录下过程,主要还是参 ... -
Ubuntu上架设PPPoE Server--转
2012-12-28 01:25 7526一。安裝 PPPoE Server Software ... -
移植rp-pppoe到s3c2440实现ADSL拨号上网--转
2012-12-28 01:22 3250一:总的来说可以分 ... -
Linux下C语言实现文件拷贝--转
2012-11-01 23:11 14009Linux下C语言实现文件拷贝 /* Func ... -
linux操作系统的DNS客户端配置
2012-09-16 16:52 11371基于linux操作系统的DNS客户端配置: Linux ... -
/etc/hosts配置文件解析
2012-06-20 14:46 2543/etc/hosts配置文件解析 这个文件可以配置主机ip及 ... -
移殖net-snmp和应用net-snmp开发详解 -转
2012-06-08 17:46 3571移殖net-snmp和应用net-snmp开发详解 @ ... -
strtok 和strtok_r 的使用
2012-06-01 17:13 106661. strtok介绍众所周知,strtok可以根据用户所提供 ... -
关于LINUX C中函数strtok使用要点
2012-06-01 15:45 2260strtok函数的使用是一个老生常谈的问题了。该函数的作用很大 ...
相关推荐
//linux只允许单进程拥有一个定时器,因此在linux下的单进程中要使用多个定时器,则需要自己维护管理 // //这个实现允许用户使用多个自定义的定时器,每个自定义的定时器将周期地被触发直到其被删除。实现的主要思路...
### Linux设备驱动中的定时器机制 #### 一、引言 在Linux内核及设备驱动开发中,定时器是十分重要的...定时器在Linux内核和设备驱动程序中扮演着非常重要的角色,理解其工作原理对于深入学习Linux内核具有重要意义。
本节我们将深入探讨Linux环境下如何使用C语言创建基于红黑树(Red-Black Tree)的多线程定时器,以及如何设置定时回调函数,其定时单位精确到毫秒。 首先,我们需要了解什么是定时器。定时器是一种机制,它可以在...
3. **可编程能力**:为了适应不同实时任务对时间参数的不同需求,RT-Linux的定时器允许在不同模式下进行编程,增强了系统的灵活性和适应性。 在实现这一改进的过程中,作者分析了x86架构的硬件时钟原理,这是构建高...
在Linux操作系统中,定时器(Timer)是一种非常重要的工具,它允许程序在特定时间间隔后执行某些操作。在软件开发中,特别是在系统级编程或服务端应用中,定时器的运用广泛,例如心跳检测、任务调度、超时处理等场景...
在Linux操作系统中,内核定时器是系统实现各种时间相关功能的关键组件。它们允许程序在特定时间间隔后执行特定操作,而无需持续消耗CPU资源。本文将深入探讨Linux内核定时器的应用及其相关概念。 首先,我们来看一...
Linux时间子系统中的高精度定时器(High Resolution Timer,简称HRTIMER)是为了解决传统低分辨率定时器精度不足的问题而引入的。在Linux内核2.6.16版本之后,高精度定时器被引入,以提供纳秒级别的定时精度,这在对...
通过编写一个程序来注册三个定时器,分别对实际时间、进程使用CPU时间、用户使用CPU时间进行计时,可以深入理解信号与定时器在Linux环境下的应用。这种练习有助于开发者掌握如何在实际项目中使用这些机制,提高程序...
根据给定的文件信息,以下是对“Linux下实时定时器的实现及应用”的详细解析,主要涵盖定时器的实现背景、内核中的时钟管理、延时机制、实时时钟的具体实现及其应用。 ### 实时定时器的实现背景 在嵌入式系统开发...
在Linux系统中,多线程编程常常涉及到时间管理和同步,以确保程序的高效与正确运行。`timerfd`和`epoll`是两种常见的机制,它们在处理多线程安全定时器方面各自扮演着重要角色。 `timerfd`是Linux内核2.6.28版本...
本文提出的“Linux下一种高性能定时器池的实现”正是针对这一问题,它利用时间轮和红黑树的数据结构,结合Linux内核的timerfd机制,设计了一个高效、低延迟的定时器池。 首先,时间轮是一种高效的定时器管理策略,...
"使用说明.txt"文件很可能是提供详细的使用教程和示例,包括如何初始化定时器、设置定时间隔、注册回调函数、启动和停止定时器等内容。这将帮助开发者快速理解和应用这个接口。 "a_good_timer_driver"文件名暗示它...
本篇文章将深入探讨如何在Linux环境下利用pthread库创建和管理定时器,以及它在实际应用中的作用。 POSIX线程库中的定时器主要由`pthread_cond_t`条件变量和`pthread_mutex_t`互斥锁配合使用,实现定时触发回调函数...
总的来说,CTimer类封装了Linux下的定时器功能,提供了一种方便的方式来在C++项目中实现定时任务,降低了开发者的编程负担,并提高了代码的可复用性。通过理解和使用CTimer,开发者可以更好地掌握Linux系统编程中的...
本文将深入探讨如何在Linux环境下创建、管理和使用应用层的定时器,以及如何通过系统调用来开启定时器。 首先,我们要了解Linux中的定时器类型。主要有两种定时器:实时定时器(Real-Time Timers)和进程定时器...
通过合理利用Linux定时器,开发者可以实现高效、精确的任务调度和时间控制。 总结,Linux定时器管理器是操作系统中不可或缺的一部分,它为程序提供了灵活的定时和调度能力。理解和掌握如何添加、删除定时器,以及...
在Linux内核中,存在两种主要类型的定时器:软定时器(software timers)和硬定时器(hardware timers)。软定时器运行在用户空间或内核空间,由软件调度;而硬定时器则基于硬件中断,通常更准确且不受CPU负载影响。...
在Linux系统中,定时器是实现程序自动化执行和时间间隔控制的关键组件。它们允许程序员设置一个时间点或间隔,让操作系统在指定的时间后执行特定的任务。在这个“Linux定时器代码”主题中,我们将深入探讨与时间相关...
在Linux系统中,定时器是实现程序自动化执行和时间间隔控制的重要工具。本文将深入探讨三种常见的定时器实现方法:最小堆、红黑树以及时间轮,并重点介绍效率最高的时间轮定时器及其应用。 首先,让我们了解最基本...