定时器
可以用系统定时器信号SIGALARM
最近工作需要于是又发现了一个新玩意timerfd配合epoll使用。
man 手册看一下
TIMERFD_CREATE(2) Linux Programmer's Manual TIMERFD_CREATE(2) NAME timerfd_create, timerfd_settime, timerfd_gettime - timers that notify via file descriptors SYNOPSIS #include <sys/timerfd.h> int timerfd_create(int clockid, int flags); int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value); int timerfd_gettime(int fd, struct itimerspec *curr_value); DESCRIPTION These system calls create and operate on a timer that delivers timer expiration notifications via a file descriptor. They provide an alternative to the use of setitimer(2) or timer_create(2), with the advantage that the file descriptor may be monitored by select(2), poll(2), and epoll(7). The use of these three system calls is analogous to the use of timer_create(2), timer_settime(2), and timer_gettime(2). (There is no analog of timer_getoverrun(2), since that functionality is provided by read(2), as described below.)
这是一个专门针对fd的定时器,通过fd可以读取定时数据(定时时间到了就会有数据回来,否则阻塞(阻塞模式))。
结合epoll使用先弄个epoll出来
/* init epoll */ int epollInit(){ int epFd = epoll_create(EPOLL_SIZE); if (epFd < 0){ perror("epoll create"); return -1; } return epFd; }
然后在弄个timerfd,并把它加入到epoll 事件中
int TimerFdInit(int epFd) { struct itimerspec new_value; /*init time*/ new_value.it_value.tv_sec = 1; new_value.it_value.tv_nsec = 0; /*time interval*/ new_value.it_interval.tv_sec = 1; new_value.it_interval.tv_nsec = 0; int timerFd = timerfd_create(CLOCK_MONOTONIC, 0); if (timerFd < 0) { cerr<<strerror(errno)<<endl; return -1; } int ret = timerfd_settime(timerFd, 0, &new_value, NULL); if (ret < 0) { cerr<<strerror(errno)<<endl; close(timerFd); return -1; } /* add to epoll */ struct epoll_event ev; ev.events = EPOLLIN | EPOLLHUP | EPOLLRDHUP; ev.data.fd = timerFd; epoll_ctl(epFd, EPOLL_CTL_ADD, timerFd, &ev); return timerFd; }
接下来就去epoll_wait循环等待这个定时器的数据
int epollHandle(int epFd, int timerFd) { struct epoll_event epEvents[EPOLL_SIZE] = {}; int timeOut = -1; uint64_t totalExp = 0; while (1) { //blocked int eventNum = epoll_wait(epFd, epEvents, EPOLL_SIZE, timeOut); if(eventNum < 0) { perror("epoll failure"); return -1; } //handle epEvents for(int i = 0; i < eventNum; ++i) { int tmpFd = epEvents[i].data.fd; if(epEvents[i].events & EPOLLIN) { if (timerFd == tmpFd) { /*handle timerFd*/ uint64_t tmpExp = 0; /*must read*/ read(timerFd, &tmpExp, sizeof(uint64_t)); totalExp += tmpExp; cout<<"timer count "<<totalExp<<endl; } } } } return 0; }