Linux下应用层定时器原本有好几种,大伙能够去搜索其余帖子博客,这里我主要描述我在使用setitimer时候遇到的问题,话很少说,直接上代码吧
linux
// lock_timmer_test.cpp
ios
#include <iostream> #include <sys/time.h> #include <signal.h> #include <linux/types.h> #include <sched.h> #include <pthread.h> using namespace std; //互斥锁 class MutexLock { public: MutexLock(){ pthread_mutex_init(&m_stMutex, NULL); } ~MutexLock(){ pthread_mutex_destroy(&m_stMutex); } void lock(){ pthread_mutex_lock(&m_stMutex);} int unlock() {return pthread_mutex_unlock(&m_stMutex); } bool trylock(){ return pthread_mutex_trylock(&m_stMutex) == 0;} pthread_mutex_t* getMutexPtr(){ return &m_stMutex;} private: pthread_mutex_t m_stMutex; }; MutexLock test_mutex; int timestep = 1; //定时器的时间间隔 //五秒切换插入map顺序 void timeout_cb(int sig) { test_mutex.lock(); std::cout<<" timer lock : "<<std::endl; test_mutex.unlock(); } //开启定时器 void set_timer() { struct sigaction sigact; sigact.sa_flags = 0; sigact.sa_handler = timeout_cb; // 设置定时器的回调函数 sigemptyset(&sigact.sa_mask); sigaction(SIGALRM, &sigact, NULL); // //结构成员it_value指定首次定时的时间, // // 结构成员it_interval指定下次定时的时间 // // 定时器工做时,先将it_value的时间值减到0, // // 发送一个信号,再将it_value赋值为it_interval的值,从新开始定时,如此反复。 struct itimerval itv; itv.it_interval.tv_sec = timestep; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = timestep; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); } int main(int argc, char const *argv[]) { set_timer(); while(true) { // test_mutex.lock(); // std::cout<<" main lock"<<std::endl; // test_mutex.unlock(); } return 0; }
编译:g++ lock_timmer_test.cpp 运行: ./a.out函数
运行结果证实:的确每隔timestep,回调函数就会被调用,执行特定任务学习
回调函数作的操做复杂后,可能因为调度问题或者是我本身代码没写好仍是其余缘由,在本例中,会出现死锁问题,查了相应的资料,有人建议回调函数不要太复杂,可能因为CPU调度问题和定时事件过短的而形成不肯定因素。
ui
因此在使用setitimer()的时候,咱们尽可能不要让回调函数作过于复杂的操做,最好只是作某些标志位的置位操做就好。spa
详情参见例四。
线程
#include <iostream> #include <sys/time.h> #include <signal.h> #include <linux/types.h> #include <sched.h> #include <pthread.h> using namespace std; //互斥锁 class MutexLock { public: MutexLock(){ pthread_mutex_init(&m_stMutex, NULL); } ~MutexLock(){ pthread_mutex_destroy(&m_stMutex); } void lock(){ pthread_mutex_lock(&m_stMutex);} int unlock() {return pthread_mutex_unlock(&m_stMutex); } bool trylock(){ return pthread_mutex_trylock(&m_stMutex) == 0;} pthread_mutex_t* getMutexPtr(){ return &m_stMutex;} private: pthread_mutex_t m_stMutex; }; MutexLock test_mutex; int timestep = 1; //五秒切换插入map顺序 void timeout_cb(int sig) { test_mutex.lock(); std::cout<<" timer lock : "<<std::endl; test_mutex.unlock(); } //五秒切换插入map顺序 void timeout_cb2(int sig) { test_mutex.lock(); std::cout<<" timer2 lock : "<<std::endl; test_mutex.unlock(); } void set_timer() { struct sigaction sigact; sigact.sa_flags = 0; sigact.sa_handler = timeout_cb; //定时器回调函数 sigemptyset(&sigact.sa_mask); sigaction(SIGALRM, &sigact, NULL); // //结构成员it_value指定首次定时的时间, // // 结构成员it_interval指定下次定时的时间 // // 定时器工做时,先将it_value的时间值减到0, // // 发送一个信号,再将it_value赋值为it_interval的值,从新开始定时,如此反复。 struct itimerval itv; itv.it_interval.tv_sec = 2*timestep; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = 2*timestep; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); } //设置uuid五秒切换插入顺序的定时器 void set_timer2() { struct sigaction sigact; sigact.sa_flags = 0; sigact.sa_handler = timeout_cb2; sigemptyset(&sigact.sa_mask); sigaction(SIGALRM, &sigact, NULL); // //结构成员it_value指定首次定时的时间, // // 结构成员it_interval指定下次定时的时间 // // 定时器工做时,先将it_value的时间值减到0, // // 发送一个信号,再将it_value赋值为it_interval的值,从新开始定时,如此反复。 struct itimerval itv; itv.it_interval.tv_sec = timestep; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = timestep; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); } int main(int argc, char const *argv[]) { set_timer(); set_timer2(); while(true) { // test_mutex.lock(); // std::cout<<" main lock"<<std::endl; // test_mutex.unlock(); } return 0; }
运行结果:code
从运行结果中能够看出,只有第二个定时器在运行,第一个被覆盖了,这对于咱们想要同时设置两种定时器的需求,貌似得不到解决(知识点的局限,应该是咱们代码有问题,还请大牛解答)。事件
因此针对须要设置多个定时器,我最后推荐使用select,或者使用libevent库中的定时器,具体参见例五,libevent的Timmer。get
#include <iostream> #include <sys/time.h> #include <signal.h> #include <linux/types.h> #include <sched.h> #include <pthread.h> using namespace std; //互斥锁 class MutexLock { public: MutexLock(){ pthread_mutex_init(&m_stMutex, NULL); } ~MutexLock(){ pthread_mutex_destroy(&m_stMutex); } void lock(){ pthread_mutex_lock(&m_stMutex);} int unlock() {return pthread_mutex_unlock(&m_stMutex); } bool trylock(){ return pthread_mutex_trylock(&m_stMutex) == 0;} pthread_mutex_t* getMutexPtr(){ return &m_stMutex;} private: pthread_mutex_t m_stMutex; }; MutexLock test_mutex; int timestep = 1; bool time_is_now = false; //五秒切换插入map顺序 void timeout_cb(int sig) { time_is_now = !time_is_now; } void set_timer() { struct sigaction sigact; sigact.sa_flags = 0; sigact.sa_handler = timeout_cb; //定时器回调函数 sigemptyset(&sigact.sa_mask); sigaction(SIGALRM, &sigact, NULL); // //结构成员it_value指定首次定时的时间, // // 结构成员it_interval指定下次定时的时间 // // 定时器工做时,先将it_value的时间值减到0, // // 发送一个信号,再将it_value赋值为it_interval的值,从新开始定时,如此反复。 struct itimerval itv; itv.it_interval.tv_sec = 2*timestep; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = 2*timestep; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); } void* lokc_unlock(void * arg) { while(true) { if(time_is_now) { test_mutex.lock(); std::cout<<" timer lock : "<<std::endl; test_mutex.unlock(); time_is_now = false;// 置位 } } } int main(int argc, char const *argv[]) { set_timer(); pthread_t autorecv_child_thread; int res; if((res=pthread_create(&autorecv_child_thread,NULL,lokc_unlock, NULL))!=0) { std::cout<<"111111111111111"<<std::endl; return -1; } if( (res = pthread_detach(autorecv_child_thread) ) != 0 ) { std::cout<<"2222222222222222"<<std::endl; return -1; } while(true) { usleep(100000); test_mutex.lock(); std::cout<<" main lock"<<std::endl; test_mutex.unlock(); } return 0; }
运行结果:
从运行结果中能够看出: 定时器回调函数只作简单任务,复杂任务交由子线程处理,这样不会出什么问题。
当须要多个定时任务同时定时操做的时候,由于本人暂时尚未找到setitimer的正确用法,所以不得不借用libevent的Timmer来实现,固然直接用select也能够,能够去搜索相应资料学习。
#include <iostream> #include <sys/time.h> #include <signal.h> #include <linux/types.h> #include <sched.h> #include <pthread.h> #include <event2/event.h> #include <event2/thread.h> #include <event2/event-config.h> using namespace std; //互斥锁 class MutexLock { public: MutexLock(){ pthread_mutex_init(&m_stMutex, NULL); } ~MutexLock(){ pthread_mutex_destroy(&m_stMutex); } void lock(){ pthread_mutex_lock(&m_stMutex);} int unlock() {return pthread_mutex_unlock(&m_stMutex); } bool trylock(){ return pthread_mutex_trylock(&m_stMutex) == 0;} pthread_mutex_t* getMutexPtr(){ return &m_stMutex;} private: pthread_mutex_t m_stMutex; }; MutexLock test_mutex; int timestep = 1; //五秒切换插入map顺序 void timeout_cb(int fd, short event, void *params) { test_mutex.lock(); std::cout<<" timmer1 lock"<<std::endl; test_mutex.unlock(); } void timeout_cb2(int fd, short event, void *params) { test_mutex.lock(); std::cout<<" timmer2 lock"<<std::endl; test_mutex.unlock(); } void* lokc_unlock(void * arg) { event_base* base = event_base_new(); struct event *timeout = NULL; struct timeval tv = {timestep, 0}; timeout = event_new(base, -1, EV_PERSIST, timeout_cb, NULL); evtimer_add(timeout, &tv); struct event *timeout2 = NULL; struct timeval tv2 = {2*timestep, 0}; timeout2 = event_new(base, -1, EV_PERSIST, timeout_cb2, NULL); evtimer_add(timeout2, &tv2); event_base_dispatch(base); event_base_free(base); } int main(int argc, char const *argv[]) { pthread_t autorecv_child_thread; int res; if((res=pthread_create(&autorecv_child_thread,NULL,lokc_unlock, NULL))!=0) { std::cout<<"111111111111111"<<std::endl; return -1; } if( (res = pthread_detach(autorecv_child_thread) ) != 0 ) { std::cout<<"2222222222222222"<<std::endl; return -1; } while(true) { } return 0; }
运行结果:
从最后结果中看,本人仍是比较推荐使用libevent这种库,毕竟使用简单,功能强大。
ps:固然对于setitimer()来讲,它支持延迟开启定时器,即itimerval 的 it_intercal 和it_value的含义,libevent对于相应的支持就须要各位本身动脑筋想办法了。(欢迎各位指教)