定时器(select、settimer)

1、select阻塞延时

#include <sys/time.h>
#include <unistd.h>
int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);

select()可以同时监视多个描述符,如果他们没有活动,则正确地将进程置于休眠状态(指select本语句休眠)。

能精确到1us,目前精确定时的最流行方案。通过使用select(),来设置定时器;原理利用select()方法的第5个参数,第一个参数设置为0,三个文件描述符集都设置为NULL,第5个参数为时间结构体,代码如下:
结果是,每隔1s打印一次,打印100次。select定时器是阻塞的,在等待时间到来之前什么都不做。要定时可以考虑再开一个线程来做。

#include <sys/time.h>
#include <sys/select.h>
#include <time.h>
#include <stdio.h>

/*seconds: the seconds; mseconds: the micro seconds*/
void setTimer(int seconds, int mseconds)
{
        struct timeval temp;

        temp.tv_sec = seconds;
        temp.tv_usec = mseconds;

        select(0, NULL, NULL, NULL, &temp);
        printf("timer\n");

        return ;
}

int main()
{
        int i;

        for(i = 0 ; i < 100; i++)
                setTimer(1, 0);

        return 0;
}

2、settimer()定时

setitimer() 不支持在同一进程中同时使用多次以实现多个定时器。一个进程中只能有一个,下一个会覆盖前一个的定时,想要在一个进程中使用多个定时器只能自己实现。

linux系统给每个进程提供了3个定时器( ITIMER_REAL、ITIMER_VIRTUAL、 ITIMER_PROF),每个定时器在各自不同的域里面计数。当任何一个timer计数到结束了,系统就发送一个信号(signal)给该进程,同时计数器重置。

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

setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。
setitimer()调用成功返回0,否则返回-1。

which为定时器类型,setitimer支持3种类型的定时器:
ITIMER_REAL: 以系统真实的时间来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL: 以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
ITIMER_PROF: 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。

struct itimerval {
struct timeval it_interval; //next value
struct timeval it_value;   //current value
};
struct timeval {
long tv_sec; //秒
long tv_usec; //微秒
};

settimer工作机制是,先对it_value倒计时,当it_value为零时触发信号,然后重置为it_interval,继续对it_value倒计时,一直这样循环下去。

it_interval指定间隔时间,it_value指定初始定时时间。如果只指定it_value,就是实现一次定时;如果同时指定
it_interval,则超时后,系统会重新初始化it_value为it_interval,实现重复定时;两者都清零,则会清除定时器。
tv_sec提供秒级精度,tv_usec提供微秒级精度,以值大的为先,注意1s = 1000000us。

ovalue用来保存先前的值,常设为NULL。

如果是以setitimer提供的定时器来休眠,只需阻塞等待定时器信号就可以了。
下面示例代码,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
int sec;
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;
	}
	fflush(stdout);
	return;
}
int main()
{
	struct itimerval value, ovalue, value2; //(1)
	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); //(2)
	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(;;);
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值