linux 下定时器的实现
2015-09-14 16:49
681 查看
最强大的定时器接口来自POSIX时钟系列,其创建、初始化以及删除一个定时器的行动被分为三个不同的函数:timer_create()(创建定时器)、timer_settime()(初始化定时器)以及timer_delete(销毁它)。
创建定时器:
int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
struct itimerspect *ovalue);
的值。如果it_interval的值为0,则定时器不是一个时间间隔定时器,一旦it_value到期就会回到未启动状态。timespec的结构提供了纳秒级分辨率
删除定时器:
int
timer_delete (timer_t timerid);
一次成功的timer_delete()调用会销毁关联到timerid的定时器并且返回0。执行失败时,此调用会返回-1并将errno设定会 EINVAL,这个唯一的错误情况代表timerid不是一个有效的定时器
实例:
c++形式:
注:
下面所指的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
创建定时器:
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
相关文章推荐
- 6个Linux chkconfig命令实例 - 增加,删除,查看和修改services的自动启动选项
- linux常用命令(23):Linux 目录结构
- cut -linux
- Linux下创建用户组及用户
- Linux 管道
- /etc/rc.d/rc与/etc/rc.d/init.d的关系介绍 linux中chkconfig 启动程序顺序
- Linux程序设计(第2版)
- 《Linux 环境C程序设计》阅读笔记
- Linux的运行级别和chkconfig用法
- linux下的C编程学习记录
- linux下网卡配vlan
- Linux脚本程序
- Linux sudo权限管理的脚本
- RabbitMQ > CentOS上安装、配置RabbitMQ
- Linux2.6.32驱动笔记(1)驱动开发概述及硬件访问技术
- 调整linux系统时区
- Centos6.5 安装ftp
- linux内核学习之四:进程切换简述
- 为Linux我们将MVC重写,有图有真相
- 【Linux】Linux软件安装方法小结(附:rpm详解)