学习笔记之定时器

定时器

1. 结构体详解

  • timer_t :timerid 定时器ID;
  • struct sigevent sev;
  • struct itimerspec it;
struct sigevent 
{	
	int sigev_notify; //通知方法
	int sigev_signo; //信号类别 
	union sigval sigev_value; //通过通知传递的数据 下有详解
	void (*sigev_notify_function)(union sigval); //用于线程运行的函数
	void *sigev_notify_attributes; //上面那个线程的属性
	pid_t sigev_notify_thread_id; //线程id
}

union sigval //通过通知传递的数据
{
	int sival_int;
	void *sival_ptr;
}
struct itimerspec 
{	
	struct timespec it_interval;  //循环时间
	struct timespec it_value;	//初次到期的时间间隔  就是延迟多长时间开始
}
	it.it_interval.tv_sec=1;//时间s
	it.it_interval.tv_nsec=0;//纳秒us.
	it.it_value.tv_sec=0;
	it.it_value.tv_nsec=0;
	

2.函数详解

1. timer_creat():创建一个新的timer;并且指定定时器到时间通知装置
2. timer_delete():删除一个timer
3. timer_gettime():获取剩余时间
4. timer_settime():开始或停止某个定时器
5. timer_getoverrun():获取丢失的定时器通知个数
int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
clock_id: 依据的时钟
evp:定时器到期产生的异步通知
*timerid:定时器id
int timer_delete(timer_t timerid)
失败返回-1,,成功返回0表示该timeid指定了无效的定时器
int timer_gettime(timer_t timerid,struct itimerspec *value);
取得一个定时器的超限运行次数:
有可能一个定时器到期了,而同一定时器上一次到期时产生的信号还处于挂起状态,未被处理。
在这种情况下,其中的一个信号可能会丢失。
这就是定时器超限。程序可以通过调用timer_getoverrun来确定一个特定的定时器出现这种超限的次数。
定时器超限只能发生在同一个定时器产生的信号上。
由多个定时器,甚至是那些使用相同的时钟和信号的定时器,所产生的信号都会排队而不会丢失。
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspect *ovalue);
new_value->it_value 如果大于 0,表示启动定时器,Timer 将在 it_value 这么长的时间过去后到期,此后每隔 it_interval 便到期一次。
如果 it_value 为 0,表示停止该 Timer。
有些时候,应用程序会先启动用一个时间间隔启动定时器,随后又修改该定时器的时间间隔,这都可以通过修改 new_value 来实现;
假如应用程序在修改了时间间隔之后希望了解之前的时间间隔设置,则传入一个非 NULL 的 old_value 指针,
这样在 timer_settime() 调用返回时,old_value 就保存了上一次 Timer 的时间间隔设置。
多数情况下我们并不需要这样,便可以简单地将 old_value 设置为 NULL,忽略它。
int timer_getoverrun(timer_t timerid);
执行成功时,timer_getoverrun()会返回定时器初次到期与通知进程(例如通过信号)定时器已到期之间额外发生的定时器到期次数。(没太懂)
举例来说,在我们之前的例子中,一个1ms的定时器运行了10ms,则此调用会返回9。
如果超限运行的次数等于或大于DELAYTIMER_MAX,则此调用会 返回DELAYTIMER_MAX。
执行失败时,此函数会返回-1并将errno设定会EINVAL,这个唯一的错误情况代表timerid指定了无效的定时器。

3. Clock ID详解

timer_creat()的参数
1. CLOCK_REALTIME:系统保存的时间,系统时间遭到篡改的时候可能会导致定时器的不准时
2. CLOCK_MONOTONIC:以当前实际走过的时间
3. CLOCK_PROCESS_CPUTIME_ID:进程实际运行的时间,即拿到cpu资源运行的时间(针对多进程)
4. CLOCK_THREAD_CPUTIME_ID:线程实际运行的时间,即拿到cpu资源运行的时间(针对多线程)

4. sev->sigev_notify到期通知的方法

1. SIGEV_SIGNAL: 发送由sev->sigev_signo指定的信号到调用进程,sigev_signo此时指定信号的类别
2. SIGEV_NONE: 什么都不做,只提供通过timer_gettime和timer_getoverrun查询超时信息。
3. SIGEV_THREAD:以sev->sigev_notification_attributes为线程属性创建一个线程, 在新建的线程内部以sev->sigev_value为参数调用evp->sigev_notification_function。
				说白了就是每次创建一个新线程,用线程运行sigev_notify_function函数,传入sigev_value作为参数,每次sigev_value修改可以改变定时发送的数据。
				sigev_notify_attributes如果非空,则是一个指向pthread_attr_t 的指针,用来设置线程的属性(比如stack大小,detach状态)
4. SIGEV_THREAD_ID: 发送sev->sigev_signo到sev->sigev_notify_thread_id指定线程id,该线程实际存在且属于当前的调用进程。

注意

SIGEV_THREAD_ID 通常和 SIGEV_SIGNAL 联合使用,这样当 Timer 到期时,系统会向由 sigev_notify_thread_id 指定的线程发送信号,否则可能进程中的任意线程都可能收到该信号

sev->sigev_signo :

  • 可靠信号与不可靠信号,实时信号与非实时信号
    • 可靠信号就是实时信号 : 信号支持排队,不会丢失,发多少次,就可以收到多少次
    • 不可靠信号就是非实时信号:信号不支持排队,信号可能会丢失,发送多次相同信号,进程只接收一次
    • [SIGRTMIN,SIGRTMAX]区间内的都是可靠信号
    • 一般可填可不填,不太懂

timer_create: 与配置绑定

define CLOCKID CLOCK_REALTIME//系统真实时间
if(timer_create(CLOCKID,&sev,&timerid)==-1)//定时器ID与sev结构体绑定
{
	perror("fail to timer_create");
	exit(-1);
}

timer_settime: 与时间绑定

		if(timer_settime(timerid,0,&it,NULL)==-1)
		{
			perror("fail to timer_settime");
			exit(-1);
		}

使用案例:

	 timer_t timerid
	 struct sigevent sev;  
	 struct itimerspec its;  
	 sev.sigev_notify = SIGEV_THREAD;  
	 sev.sigev_signo = SIGRTMIN;  
	 sev.sigev_value.sival_ptr = timerid;
	 sev.sigev_value.sival_int=2
	 sev.sigev_notify_function = send_dog;
	 sev.sigev_notify_attributes = NULL;  
	 if(timer_create(CLOCK_REALTIME,&sev,&timerid)==-1)
	{
		perror("fail to timer_create");
		exit(-1);
	}
	 its.it_value.tv_nsec=10;
	 its.it_value.tv_sec=0;
	 its.it_interval.tv_sec =1;  
	 its.it_interval.tv_nsec =0;  
	 if(timer_settime(timerid, 0, &its, NULL) == -1)  
	 {  
			perror("fail to timer_settime");
			exit(-1);
	 } 

void send_dog(union sigval v)
{
	cout<<"test:"<<v.sival_int<<endl;//每次运行这个函数的线程都不一样
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值