免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: wyezl

epoll模型的使用及其描述符耗尽问题的探讨 [复制链接]

论坛徽章:
0
发表于 2006-08-22 11:43 |显示全部楼层
刚才测试了lz的程序。
50个并发,cfd最大达到37然后回落到5。

如上测试多次没有发现cfd有增大的趋势。
所以感觉和内核版本有关系。

测试环境:

kernel 2.6.15
gcc 4.0.3

distribution:ubuntu

论坛徽章:
0
发表于 2006-08-22 11:47 |显示全部楼层
下面这个模型我也用过。不过效率很底。


#include <iostream>

#include <sys/socket.h>

#include <sys/epoll.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdio.h>



#define MAXLINE 10

#define OPEN_MAX 100

#define LISTENQ 20

#define SERV_PORT 5555

#define INFTIM 1000



void setnonblocking(int sock)

{

  int opts;

  opts=fcntl(sock,F_GETFL);

  if(opts<0)

  {

      perror("fcntl(sock,GETFL)");

      exit(1);

  }

  opts = opts|O_NONBLOCK;

  if(fcntl(sock,F_SETFL,opts)<0)

  {

      perror("fcntl(sock,SETFL,opts)");

      exit(1);

  }   

}



int main()

{

  int i, maxi, listenfd, connfd, sockfd,epfd,nfds;

  ssize_t n;

  char line[MAXLINE];

  socklen_t clilen;

  //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件

  struct epoll_event ev,events[20];

  //生成用于处理accept的epoll专用的文件描述符

  epfd=epoll_create(256);



  struct sockaddr_in clientaddr;

  struct sockaddr_in serveraddr;

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  //把socket设置为非阻塞方式

  setnonblocking(listenfd);

  //设置与要处理的事件相关的文件描述符

  ev.data.fd=listenfd;

  //设置要处理的事件类型

  ev.events=EPOLLIN|EPOLLET;

  //注册epoll事件

  epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);



  bzero(&serveraddr, sizeof(serveraddr));

  serveraddr.sin_family = AF_INET;



  char *local_addr="200.200.200.204";

  inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT);

  serveraddr.sin_port=htons(SERV_PORT);

  bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));

  listen(listenfd, LISTENQ);



  maxi = 0;

  for ( ; ; ) {

      //等待epoll事件的发生

      nfds=epoll_wait(epfd,events,20,500);

      //处理所发生的所有事件     

      for(i=0;i<nfds;++i)

      {

          if(events[i].data.fd==listenfd)

          {



            connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);

            if(connfd<0){

                perror("connfd<0");

                exit(1);

            }

            setnonblocking(connfd);



            char *str = inet_ntoa(clientaddr.sin_addr);

            std::cout<<"connect from "<_u115 ?tr<<std::endl;

            //设置用于读操作的文件描述符

            ev.data.fd=connfd;

            //设置用于注测的读操作事件

            ev.events=EPOLLIN|EPOLLET;

            //注册ev

            epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);

          }

          else if(events[i].events&EPOLLIN)

          {

            if ( (sockfd = events[i].data.fd) < 0) continue;

            if ( (n = read(sockfd, line, MAXLINE)) < 0) {

                if (errno == ECONNRESET) {



                    close(sockfd);

                    events[i].data.fd = -1;

                } else

                    std::cout<<"readline error"<<std::endl;

            } else if (n == 0) {

                close(sockfd);

                events[i].data.fd = -1;

            }

            //设置用于写操作的文件描述符

            ev.data.fd=sockfd;

            //设置用于注测的写操作事件

            ev.events=EPOLLOUT|EPOLLET;

            //修改sockfd上要处理的事件为EPOLLOUT

            epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);

          }

          else if(events[i].events&EPOLLOUT)

          {   

            sockfd = events[i].data.fd;

            write(sockfd, line, n);

            //设置用于读操作的文件描述符

            ev.data.fd=sockfd;

            //设置用于注测的读操作事件

            ev.events=EPOLLIN|EPOLLET;

            //修改sockfd上要处理的事件为EPOLIN

            epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);

          }



      }



  }

}

论坛徽章:
0
发表于 2006-08-22 11:50 |显示全部楼层
原帖由 nuclearweapon 于 2006-8-22 11:43 发表
刚才测试了lz的程序。
50个并发,cfd最大达到37然后回落到5。

如上测试多次没有发现cfd有增大的趋势。
所以感觉和内核版本有关系。

测试环境:

kernel 2.6.15
gcc 4.0.3

distribution:ubuntu


50个并发,cfd最大达到37然后回落到5。 是有这样的现象。所以我说是增大趋势。而没有说直线增长。

这也不是你几分钟就能测试出来的。1024个fd也需要一个多小时才能耗尽(大约处理100万请求)。而且是量比较大的线上测试。

论坛徽章:
0
发表于 2006-08-22 11:57 |显示全部楼层
原帖由 wyezl 于 2006-8-22 11:50 发表


50个并发,cfd最大达到37然后回落到5。 是有这样的现象。所以我说是增大趋势。而没有说直线增长。

这也不是你几分钟就能测试出来的。1024个fd也需要一个多小时才能耗尽(大约处理100万请求)。而且是量比较 ...


你这里说的耗尽是什么意思?

表示Accept不能再接受client了吗?

论坛徽章:
0
发表于 2006-08-22 12:02 |显示全部楼层
就调试来说,当服务程序挂起的时候
你可以看如下目录:
/proc/your_process_id/fd

看一看有那些fd在被你的进程使用!

论坛徽章:
0
发表于 2006-08-22 12:38 |显示全部楼层
你另外一个模型就是epoll例子的模型吧
凭什么说人家的就效率低了?

论坛徽章:
0
发表于 2006-08-22 13:10 |显示全部楼层
原帖由 星之孩子 于 2006-8-22 12:38 发表
你另外一个模型就是epoll例子的模型吧
凭什么说人家的就效率低了?



我测试过。处理能力底了20%。

论坛徽章:
0
发表于 2006-08-22 13:11 |显示全部楼层
to LZ,

你做什么服务? 有多少同时连接?

论坛徽章:
0
发表于 2006-08-22 13:18 |显示全部楼层
原帖由 nuclearweapon 于 2006-8-22 12:02 发表
就调试来说,当服务程序挂起的时候
你可以看如下目录:
/proc/your_process_id/fd

看一看有那些fd在被你的进程使用!


我一共监视了5000个描述符,程序跑了一天,基本上快耗完了。还剩不到1000个了。


ls /proc/24152/fd/
Display all 4051 possibilities? (y or n)

可见这些耗尽的描述符都在使用中。 但不知道什么地方没把它们释放。

论坛徽章:
0
发表于 2006-08-22 13:22 |显示全部楼层
原帖由 思一克 于 2006-8-22 13:11 发表
to LZ,

你做什么服务? 有多少同时连接?


http服务。简单的数据。基本上是读取内存的操作。类似股票行情数据。

当然每秒能处理越多请求越好。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP