首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >epoll (EPOLLET)依赖于读取字节的计数?

epoll (EPOLLET)依赖于读取字节的计数?
EN

Stack Overflow用户
提问于 2013-03-22 12:03:47
回答 1查看 1.8K关注 0票数 0

我在边缘触发模式下使用epoll。为了避免饥饿,代码一次从一个套接字读取MAX_FREAD_LENGTH字节。然后,将片段组装到EOL发生为止。我注意到,当MAX_FREAD_LENGTH很小时,epoll就会卡住。我认为它应该适用于任何大小的阅读块。它可以处理512字节,但有时挂起(意味着没有EPOLLIN事件)。如果我增加MAX_FREAD_LENGTH,它就会变得更稳定。我怎样才能解决这个问题?

非常感谢你考虑我的问题!

EPOLL初始化

代码语言:javascript
复制
int res;
epFd = epoll_create(EPOLL_SIZE);
event.data.fd = serverFd;
event.events = EPOLLIN|EPOLLET;
res=epoll_ctl(epFd, EPOLL_CTL_ADD, serverFd, &event);
if (res == -1){
  perror ("epoll_ctl error: ");
  return EH_ERROR;
}
events = calloc (MAX_EVENTS, sizeof event);

注册净事件:

代码语言:javascript
复制
while (TRUE){
  int nfds;
  do{
    nfds = epoll_wait(epFd, events, MAX_EVENTS, -1);
  } while (nfds < 0 && errno == EINTR);

  int i = 0;
  for (;i<nfds;i++){
    if ( (events[i].data.fd == serverFd) && (events[i].events & EPOLLIN)){
      if ((clientFd = accept(serverFd,(struct sockaddr *) &clientAddr, &clientLen)) < 0){
        char log[255];
        sprintf(log,"dispatch_net_event: Socket accept failed: %s",strerror(errno));
        logger->log(LOGG_ERROR,log);
      }
      if(newclient(clientFd)!=EH_ERROR){
        /* client created */
        setnonblocking(fd,NONBLOCKING);
        event.data.fd = clientFd;
        event.events = EPOLLIN |EPOLLET;
        if(epoll_ctl(epFd, EPOLL_CTL_ADD, fd, &event)<0){
          fprintf(stderr,"Epoll insertion error (fd=%d): ",clientFd);
          return EH_ERROR;             
        }    
        continue;
      }
      else{
        logger->log(LOGG_ERROR,"Client creation error");
        continue;
      }
    }
    else{
     dispatch_event(events[i].data.fd,NET_EVENT);
    }
  }
}

处理净事件

代码语言:javascript
复制
#define SMTP_MAX_LINE_LENGTH MAX_FREAD_LENGTH
ssize_t count;
char buf[SMTP_MAX_LINE_LENGTH];

memset(buf,'\0', SMTP_MAX_LINE_LENGTH);
count = read (fd, buf,MAX_FREAD_LENGTH );

if (count==-1){
  if (errno == EAGAIN)
    return KEEP_IT;
  else if (errno == EWOULDBLOCK)
    return KEEP_IT;
  else{
    char log[255];
    sprintf(log,"handle_net_event: Read error: %s",strerror(errno));
    logger->log(LOGG_ERROR,log);
  }
}
else{   /* count > 0 there are data in the buffer */
  /* assemble possible partial lines, TRUE if line is whole (end with \r\n)*/
  whole=assemble_line(count,client,&buf[0]);
}
 /* process the line */

编辑:

我忘了提到,epoll运行在一个单独的线程中,而不是其他部分。

EN

回答 1

Stack Overflow用户

发布于 2013-03-22 12:46:50

我觉得你用错了EPOLLET。尝试不使用EPOLLET (即使用级别触发模式),并查看这是否有效。如果是这样的话,这意味着您的根本问题是,您没有执行边缘触发模式所要求的操作,即继续从任何就绪描述符中读取,直到得到EAGAIN为止。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15569845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档