POSIX定时器

最强大的定时器接口来自POSIX时钟系列,其创建、初始化以及删除一个定时器的行动被分为三个不同的函数:timer_create()(创建定时器)、timer_settime()(初始化定时器)以及timer_delete(销毁它)。

 

创建一个定时器:

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

    进程可以通过调用timer_create()创建特定的定时器,定时器是每个进程自己的,不是在fork时继承的。clock_id说明定时器是基于哪个时钟的,*timerid装载的是被创建的定时器的ID。该函数创建了定时器,并将他的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设定为如下值来定制定时器到期后的行为:

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

SIGEV_SIGNAL: 当定时器到期,内核会将sigev_signo所指定的信号传送给进程。在信号处理程序中,si_value会被设定会sigev_value。

SIGEV_THREAD: 当定时器到期,内核会(在此进程内)以sigev_notification_attributes为线程属性创建一个线程,并且让它执行sigev_notify_function,传入sigev_value作为为一个参数

 

启动一个定时器:

    timer_create()所创建的定时器并未启动。要将它关联到一个到期时间以及启动时钟周期,可以使用timer_settime()。

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

 

struct itimespec{

    struct timespec it_interval; 

    struct timespec it_value;   

}; 

    如同settimer(),it_value用于指定当前的定时器到期时间。当定时器到期,it_value的值会被更新成it_interval 的值。如果it_interval的值为0,则定时器不是一个时间间隔定时器,一旦it_value到期就会回到未启动状态。timespec的结构提供了纳秒级分辨率:

struct timespec{

    time_t tv_sec;

    long tv_nsec;  

};

    如果flags的值为TIMER_ABSTIME,则value所指定的时间值会被解读成绝对值(此值的默认的解读方式为相对于当前的时间)。这个经修改的行为可避免取得当前时间、计算“该时间”与“所期望的未来时间”的相对差额以及启动定时器期间造成竞争条件。

    如果ovalue的值不是NULL,则之前的定时器到期时间会被存入其所提供的itimerspec。如果定时器之前处在未启动状态,则此结构的成员全都会被设定成0。

 

 

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

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

 

取得一个定时器的超限运行次数:

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

int timer_getoverrun(timer_t timerid);

    执行成功时,timer_getoverrun()会返回定时器初次到期与通知进程(例如通过信号)定时器已到期之间额外发生的定时器到期次数。举例来说,在我们之前的例子中,一个1ms的定时器运行了10ms,则此调用会返回9。如果超限运行的次数等于或大于DELAYTIMER_MAX,则此调用会返回DELAYTIMER_MAX。

    执行失败时,此函数会返回-1并将errno设定会EINVAL,这个唯一的错误情况代表timerid指定了无效的定时器。

 

删除一个定时器:

int timer_delete (timer_t timerid);

    一次成功的timer_delete()调用会销毁关联到timerid的定时器并且返回0。执行失败时,此调用会返回-1并将errno设定会 EINVAL,这个唯一的错误情况代表timerid不是一个有效的定时器。

 

例1:

void  handle()
{
 time_t t;
 char p[32];

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

 printf("time is %sn", p);
}

 

int main()
{
 struct sigevent evp;
 struct itimerspec ts;
 timer_t timer;
 int ret;

 evp.sigev_value.sival_ptr = &timer;
 evp.sigev_notify = SIGEV_SIGNAL;
 evp.sigev_signo = SIGUSR1;
 signal(SIGUSR1, handle);

 ret = timer_create(CLOCK_REALTIME, &evp, &timer);
 if( ret )
  perror("timer_create");

 ts.it_interval.tv_sec = 1;
 ts.it_interval.tv_nsec = 0;
 ts.it_value.tv_sec = 3;
 ts.it_value.tv_nsec = 0;

 ret = timer_settime(timer, 0, &ts, NULL);
 if( ret )
  perror("timer_settime");

 while(1);
}

 

例2:

void  handle(union sigval v)
{
 time_t t;
 char p[32];

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

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

 

int main()
{
 struct sigevent evp;
 struct itimerspec ts;
 timer_t timer;
 int ret;

 memset   (&evp,   0,   sizeof   (evp));
 evp.sigev_value.sival_ptr = &timer;
 evp.sigev_notify = SIGEV_THREAD;
 evp.sigev_notify_function = handle;
 evp.sigev_value.sival_int = 3;   //作为handle()的参数

 ret = timer_create(CLOCK_REALTIME, &evp, &timer);
 if( ret)
  perror("timer_create");

 ts.it_interval.tv_sec = 1;
 ts.it_interval.tv_nsec = 0;
 ts.it_value.tv_sec = 3;
 ts.it_value.tv_nsec = 0;

 ret = timer_settime(timer, TIMER_ABSTIME, &ts, NULL);
 if( ret )
  perror("timer_settime");

 while(1);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/435359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python append函数_让你python代码更快的3个小技巧!速度提高了一倍还多

大家好!今天呢,我们来聊一聊如何加速你的 python 代码。Python 语言的优点可以列举出许多,语法简单易懂、模块丰富、应用广泛等等。但是世界上没有有完美的东西,python 一个明显缺点就是运行速度慢,至少跟 C 语言没法比…

扣扣保镖我喜欢

扣-扣-保-镖还是挺好用的,上次360召回之后,网上的下载链接都失效了,不过今天偶然发现我的硬盘上还有一份。。就打开试试,结果没事的哈。 qq版本:qq2010正式版 sp2.1(1861) 趣盘下载地址:http://oskycar.qup…

栅格计算面积

1.进行栅格重分类 2.重分类 3.打开属性,查看像元大小 4.打开属性表 5.添加字段 6.打开字段计算器 7.计算结果如下(单位一般为平方米)

autotools使用

Makefile固然可以帮助make完成它的使命,但要承认的是,编写Makefile确实不是一件轻松的事,尤其对于一个较大的项目而言更是如此。那么,有没有一种轻松的手段生成Makefile而同时又能让我们享受make的优越性呢?本节要讲au…

LSGO软件技术团队2015~2016学年第十三周(1123~1129)总结

团队简述: LSGO软件技术团队成立于2010年10月,主要从事的应用方向为互联网与移动互联网(UI设计,前端开发,后台开发),地理信息系统;研究方向为大数据处理与机器学习。成立几年来为学校…

[转]揭开正则表达式的神秘面纱

揭开正则表达式的神秘面纱关闭高亮[原创文章,转载请保留或注明出处:http://www.regexlab.com/zh/regref.htm]引言正则表达式(regular expression)就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符…

智能机器人及其应用ppt课件_一文了解!伺服系统机理及其在工业机器人等领域的应用...

更多,更及时的干货内容,请加我们的微信公众号:wc_sfdj诚邀业内人士及机构向我们投稿,投稿有礼投稿邮箱:tougao51wctt.com来源 | 网络欢迎阅读本篇文章,文末有福利哦!(一)伺服系统综述1、伺服运动…

利用python爬取房价

​公众号二维码 爬取房价网站:(安居客)https://zb.fang.anjuke.com/loupan/all/ 由于该网站每隔一段时间需要进行验证(反爬虫),所以我们为了防止我们爬取信息的时候出现间断,所以需要借助execl来保证信息的连续性。 结果展示

Linux编程make命令

摘要:在开发一个系统时,一般是将一个系统分成几个模块,这样做提高了系统的可维护性,但由于各个模块间不可避免存在关联,所以当一个模块改动后,其他模块也许会有所更新,当然对小系统来说,手工编译…

python 计算订单_python实现apriori算法的关联规则之支持度、置信度、提升度

Apriori算法的简介 Apriori算法:使用候选项集找频繁项集 Apriori算法是一种最有影响的挖掘布尔关联规则频繁项集的算法。其核心是基于两阶段频集思想的递推算法。该关联规则在分类上属于单维、单层、布尔关联规则。在这里,所有支持度大于最小支持度的项集…

LSGO软件技术团队2015~2016学年第十四周(1130~1206)总结

团队简述: LSGO软件技术团队成立于2010年10月,主要从事的应用方向为互联网与移动互联网(UI设计,前端开发,后台开发),地理信息系统;研究方向为大数据处理与机器学习。成立几年来为学校…

java安装和环境配置

下载jdk 网址为https://www.oracle.com/java/technologies/javase-downloads.html 2.安装jdk 3.配置环境 以下都是在系统变量下新建 为jdk安装目录 D:\Program Files\Java\jdk-15.0.2 .;%JAVA_HOME%\bin;%JAVA_HOME%\lib\tool.jar; %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; 4.…

在Windows Azure中使用自己的域名

请参考:http://blog.smarx.com/posts/custom-domain-names-in-windows-azure 本文是对这篇文章部分解释和补充。 并请记住,此博客总是能给你在Windows Azure的开发中带来帮助。 域名解析机制浅析 域名解析,本是个很简单的事情:我们如若想将我…

如何使用autotools工具

autotools是系列工具,读者首先要确认系统是否装了以下工具(可以用which命令进行查看)。 autoscanaclocalautoheaderautomakeautoconf 使用autotools主要就是利用各个工具的脚本文件以生成最后的Makefile。其总体流程是这样的: 使…

LSGO软件技术团队2015~2016学年第十五周(1207~1213)总结

团队简述: LSGO软件技术团队成立于2010年10月,主要从事的应用方向为互联网与移动互联网(UI设计,前端开发,后台开发),地理信息系统;研究方向为大数据处理与机器学习。成立几年来为学校…

python代码太长_Python 太糟糕了?开发者总结了 8 大原因

作者对每一项“缺点”都进行了分析,全文洋洋洒洒,概括起来 8 个原因分别是: 1、版本不兼容 Python 3 与 Python 2 不完全兼容。作者以 Perl 语言和创造了世界上早期个人电脑的 Commodore 为例,分析了缺乏向后兼容性和分离版本是如…

Tomca安装

下载 官网: http://tomcat.apache.org/ 2.安装 默认 3.安装成功

知其所以然(续)

查了一下,上篇知其所以然(以学习算法为例) 是08年7月写的,现在已经是10年11月,过去了两年零4个月,这说明了三件事情:1,一个问题其实你可以一直放在脑子里面,利用暗时间 对…

python中的引用怎么理解_Python函数通过引用调用

基本上有三种函数调用:通过价值 通过引用传递 通过对象引用传递 Python是一种PASS-BY-OBJECT-REFERENCE编程语言。 首先,重要的是要理解一个变量,变量(对象)的值是两个独立的东西。变量指向对象。变量不是对象。再次&a…

ELF动态库加载技术

库用于将相似函数打包在一个单元中。Linux支持两种类型的库:静态库(在编译时静态绑定到程序)和动态库(在运行时绑定到程序)。Linux系统使用的动态库是ELF格式,后缀名为so。 1 加载 动态库内部划分为段&a…