linux 下定时器的实现

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

创建定时器:

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

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
}
启动定时器:

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;   

}; 
struct timespec{

    time_t tv_sec;

    long tv_nsec;  

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

int timer_delete (timer_t timerid);

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

实例:

#include<stdio.h>
#include<iostream>
#include<signal.h>
#include <string.h>
#include<time.h>
#include <stddef.h>
#include <sstream>
#include <iomanip>
using namespace std;

void testfunc(int signo, siginfo_t* info, void* context);
int cnt;

int main(int argc, char *argv[])
{
	cnt = 0;
    timer_t timeID;
	struct sigevent evp;
	memset(&evp, 0, sizeof(evp));
	evp.sigev_notify = SIGEV_SIGNAL;
	evp.sigev_signo = SIGRTMAX;
	evp.sigev_value.sival_ptr = &timeID;

	if(timer_create(CLOCK_REALTIME, &evp, &timeID) ==-1 )
	{
		cout << "err" << endl;
		return -1;
	}

	struct sigaction sigac;
	sigemptyset(&sigac.sa_mask);
	sigac.sa_flags = SA_SIGINFO;
	sigac.sa_sigaction = testfunc;
	sigaction(SIGRTMAX, &sigac, NULL);
   
	struct itimerspec it;  
    it.it_interval.tv_sec = 2;  
    it.it_interval.tv_nsec = 0;  
    it.it_value.tv_sec = 2;  
    it.it_value.tv_nsec = 0;

	if(timer_settime(timeID, 0, &it, NULL) == -1)
	{
		cout << "err" << endl;
		timer_delete(timeID);
		return -1;
	}

	while(cnt < 1000);
    return 0;
}

void testfunc(int signo, siginfo_t* info, void* context)
{
	// cnt++;
	// cout << cnt << endl;
	struct tm *t;
	time_t timer = time(NULL);
	t = localtime(&timer);
	ostringstream os;
	os.fill('0');
	os << setw(4) << t->tm_year + 1900 << '-'
	   << setw(2) << t->tm_mon + 1 << '-'
	   << setw(2) << t->tm_mday << ' '        
	   << setw(2) << t->tm_hour << ':'
	   << setw(2) << t->tm_min  << ':'
	   << setw(2) << t->tm_sec  << ends;
	cout << os.str() << endl;
}

//g++ -g -o sigaction sigaction.cpp -lrt


c++形式:

#include<stdio.h>  
#include<iostream>  
#include<signal.h>  
#include <string.h>  
#include<time.h>  
#include <stddef.h>  
#include <sstream>  
#include <iomanip>  
using namespace std;



class CTimeTask
{
public:
	typedef void(*func)(int signo, siginfo_t* info, void* context);
    CTimeTask()
	{
		memset(&evp, 0, sizeof(evp));  
		evp.sigev_notify = SIGEV_SIGNAL;  
		evp.sigev_signo = SIGRTMAX;  
		evp.sigev_value.sival_ptr = &timeID;
		if(::timer_create(CLOCK_REALTIME, &evp, &timeID) ==-1 )  
		{  
			cout << "timer create err" << endl;  
			return;  
		}  
	}
    virtual ~CTimeTask()
	{}

    int excuteTask(int sec, int nsec, func onFunc)
	{
		struct sigaction sigac;  
		sigemptyset(&sigac.sa_mask);  
		sigac.sa_flags = SA_SIGINFO;  
		sigac.sa_sigaction = onFunc;  
		sigaction(SIGRTMAX, &sigac, NULL);  
     
		struct itimerspec it;    
		it.it_interval.tv_sec = sec;    
		it.it_interval.tv_nsec = nsec;    
		it.it_value.tv_sec = sec;    
		it.it_value.tv_nsec = nsec;  
  
		if(::timer_settime(timeID, 0, &it, NULL) == -1)  
		{  
			cout << "set time task err" << endl;  
			::timer_delete(timeID);  
			return -1;  
		}  
	}
	static CTimeTask* getInstance()
	{
		if(timeTask == NULL)
			timeTask =  new CTimeTask();
		return timeTask;
	}
private:
	timer_t timeID;  
    struct sigevent evp;
	static CTimeTask *timeTask;
};
CTimeTask* CTimeTask::timeTask = NULL;
#define Task CTimeTask::getInstance()

void testfunc(int signo, siginfo_t* info, void* context)  
{  
    // cnt++;  
    // cout << cnt << endl;  
    struct tm *t;  
    time_t timer = time(NULL);  
    t = localtime(&timer);  
    ostringstream os;  
    os.fill('0');  
    os << setw(4) << t->tm_year + 1900 << '-'  
       << setw(2) << t->tm_mon + 1 << '-'  
       << setw(2) << t->tm_mday << ' '          
       << setw(2) << t->tm_hour << ':'  
       << setw(2) << t->tm_min  << ':'  
       << setw(2) << t->tm_sec  << ends;  
    cout << os.str() << endl;  
}

int main(int argc, char *argv[])
{
	//CTimeTask timeTask;
	//CTimeTask::getInstance()->excuteTask(2, 0, testfunc);
	Task->excuteTask(2, 0, testfunc);
	while(1);
    return 0;
}



注:

下面所指的signal都是指以前的older signal函数,现在大多系统都用sigaction重新实现了signal函数
1、signal在调用handler之前先把信号的handler指针恢复;sigaction调用之后不会恢复handler指针,直到再次调用sigaction修改handler指针。
:这样,(1)signal就会丢失信号,而且不能处理重复的信号,而sigaction就可以。因为signal在得到信号和调用handler之间有个时间把handler恢复了,这样再次接收到此信号就会执行默认的handler。(虽然有些调用,在handler的以开头再次置handler,这样只能保证丢信号的概率降低,但是不能保证所有的信号都能正确处理)
2、signal在调用过程不支持信号block;sigaction调用后在handler调用之前会把屏蔽信号(屏蔽信号中自动默认包含传送的该信号)加入信号中,handler调用后会自动恢复信号到原先的值。
(2)signal处理过程中就不能提供阻塞某些信号的功能,sigaction就可以阻指定的信号和本身处理的信号,直到handler处理结束。这样就可以阻塞本身处理的信号,到handler结束就可以再次接受重复的信号。
3、sigaction提供了比signal多的多的功能,可以参考man

参考:
http://blog.sina.com.cn/s/blog_71bc0b1901017gxw.html
http://www.ccvita.com/508.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值