0

0

最强大的定时器接口来自POSIX时钟系列,你知道吗?

WBOY

WBOY

发布时间:2024-03-10 11:40:03

|

1204人浏览过

|

来源于ITcool

转载

最强悍的定时器插口来自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。假如要形成除默认讯号之外的其它讯号linux,程序必须将evp->sigev_signo设置为期望的信号码。structsigevent结构中的成员evp->sigev_notify说明了定时器到期时应当采取的行动。一般,这个成员的值为SIGEV_SIGNAL,这个值说明在定时器到期时,会形成一个讯号。程序可以将成员evp->sigev_notify设为SIGEV_NONE来避免定时器到期时形成讯号。

假如几个定时器形成了同一个讯号,处理程序可以用evp->sigev_value来分辨是那个定时器形成了讯号。要实现这些功能,程序必须在为讯号安装处理程序时,使用structsigaction的成员sa_flags中的标志符SA_SIGINFO。

clock_id取值为以下:

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设定为如下值来定制定时器到期后的行为:

启动一个定时器:

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所指定的时间值会被剖析成绝对值(此值的默认的剖析方法为相对于当前的时间)。这个经更改的行为可防止取得当前时间、计算“该时间”与“所期望的未来时间”的相对差额以及启动定时器期间导致竞争条件。

定时器程序设计实验报告_linux 定时器程序_定时器程序编写

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

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

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

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

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

int timer_delete (timer_t timerid);

执行成功时,timer_getoverrun()会返回定时器初次到期与通知进程(比如通过讯号)定时器已到期之间额外发生的定时器到期次数。举例来说linux 定时器程序,在我们之前的事例中,一个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:

voidhandle()

time_tt;

charp[32];

time(&t);

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

printf("timeis%s/n",p);

intmain()

structsigeventevp;

structitimerspects;

timer_ttimer;

intret;

evp.sigev_value.sival_ptr=&timer;

evp.sigev_notify=SIGEV_SIGNAL;

evp.sigev_signo=SIGUSR1;

定时器程序设计实验报告_定时器程序编写_linux 定时器程序

signal(SIGUSR1,handle);

ret=timer_create(CLOCK_REALTIME,&evp,&timer);

if(ret)

perror("timer_create");

_sec=1;

_nsec=0;

_sec=3;

_nsec=0;

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

if(ret)

perror("timer_settime");

while(1);

例2:

voidhandle(unionsigvalv)

time_tt;

charp[32];

time(&t);

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

printf("%sthread%lu,val=%d,signalcaptured./n",p,pthread_self(),v.sival_int);

return;

intmain()

structsigeventevp;

structitimerspects;

timer_ttimer;

intret;

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

定时器程序设计实验报告_linux 定时器程序_定时器程序编写

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

_sec=1;

_nsec=0;

_sec=3;

_nsec=0;

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

if(ret)

perror("timer_settime");

while(1);

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

231

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

436

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

749

2023.08.22

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

90

2023.09.25

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

73

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

281

2023.11.28

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1023

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

66

2025.10.17

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

72

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

【web前端】Node.js快速入门
【web前端】Node.js快速入门

共16课时 | 2万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号