我想使用it_interval
of newValue
来设置超时的间隔.
但在我的例子中,我只能打印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;
}
Run Code Online (Sandbox Code Playgroud)
Arm*_*igo 18
这是因为您正在使用EPOLLET而不是读取()生成到tfd中的数据.定时器到期"写入"需要读取的8个字节的数据:您确实需要读取它.打印"超时"时添加此项:
uint64_t value;
read(tfd, &value, 8);
Run Code Online (Sandbox Code Playgroud)
更详细:EPOLLET要求进行边沿触发,这意味着epoll_wait()只会在文件descritor tfd上说"数据准备输入",直到您读取该数据为止.换句话说,只要您没有读取该数据,将来对epoll_wait()的调用将不会再次返回相同的描述符.这种行为对于普通套接字很有用,例如,如果你在主线程中执行epoll_wait(),请注意一些数据已准备就绪,然后启动另一个线程来读取它.主线程立即返回epoll_wait().但我们不希望它再次立即唤醒,即使文件描述符中的数据可能尚未被读取.
请注意,我猜你没有EPOLLET的例子也是错误的,因为你没有读取(),tfd在初始延迟后总是可读的,所以它会在初始延迟后尽快打印"超时"到期.