我想使用newValue
的it_interval
来设置超时间隔。
但在我的例子中,我只能打印timeout
一次 。
发生了什么? 我如何设置间隔?
这是我的代码:
int main() { int efd =epoll_create(256); setnonblock(efd); struct epoll_event ev,events[256]; int tfd;//timer fd if((tfd= timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0) cout<<"timerfd create error"<<endl; struct itimerspec newValue; struct itimerspec oldValue; bzero(&newValue,sizeof(newValue)); bzero(&oldValue,sizeof(oldValue)); struct timespec ts; ts.tv_sec = 5; ts.tv_nsec = 0; //both interval and value have been set newValue.it_value = ts; newValue.it_interval = ts; if( timerfd_settime(tfd,0,&newValue,&oldValue) <0) { cout<<"settime error"<<strerror(errno)<<endl; } ev.data.fd = tfd; ev.events = EPOLLIN | EPOLLET; if( epoll_ctl(efd,EPOLL_CTL_ADD,tfd,&ev) < 0) cout<<"epoll_ctl error"<<endl; int num = 0; while(1) { if((num=epoll_wait(efd,events,256,1000)) > 0) {//justice for(int i=0;i<num;i++) { if(events[i].data.fd == tfd) { cout<<"timeout"<<endl; } } } } return 0; }
这是因为您正在使用EPOLLET,而不是将生成的数据读入tfd。 计时器的到期“写入”需要被读取的8个字节的数据:你真的需要读取它。 当你打印“超时”时添加这个:
uint64_t value; read(tfd, &value, 8);
更多细节:EPOLLET要求边沿触发,这意味着epoll_wait()只会在文件描述符tfd上说“数据准备好输入”一次,直到读取数据为止。 换句话说,只要你没有读取这些数据,以后对epoll_wait()的调用将不会再返回相同的描述符。 这个行为对于普通套接字是有用的,例如,如果在主线程中执行epoll_wait(),注意一些数据已经准备好,然后触发另一个线程来读取它。 主线程立即返回到epoll_wait()。 但是我们不希望它立即再次唤醒,即使文件描述符中的数据可能还没有被读取。
请注意,我猜你没有使用EPOLLET的例子也是错误的,因为你不读取(),tfd在初始延迟之后总是可读的,所以在初始延迟之后它会尽可能快地打印“timeout”到期。