zoukankan      html  css  js  c++  java
  • select、poll、epoll的区别以及epoll的两种模式(LT、ET)以及实现

    引自:https://blog.csdn.net/qq_41038824/article/details/88537640

    select和poll的缺点:

    (1)、每轮循环都要从用户空间往内核空间拷贝数据;

    (2)、内核轮询,检测每个描述符有没有就绪事件,O(n);

    (3)、I/O函数返回后,遍历每个描述符找到有事件就绪的描述符,O(n);

    (select、poll)和(epoll)的区别:

    (1)、select、poll每次循环都需要从用户空间向内核空间传递数据;

                 epoll直接在内核空间创建事件表,每个描述符只需要传递一次;

    (2)、select、poll在内核中以轮询的方式检测就绪事件描述符;

                 epoll在每个描述符上注册回调函数,事件就绪后执行回调函数将描述符添加到就绪队列;

    (3)、select、epoll返回后,需要遍历所有文件描述符,才能找到就绪的文件描述符;

                 epoll返回后,直接得到就绪描述符不需要遍历所有描述符;

    epoll的两种模式:

    (1)、LT模式(电平触发):描述符事件就绪后,如果用户没有处理完数据,epoll会一直提醒,直到处理完成;代码实现(epoll-LT.c

    (2)、ET模式(边沿触发):高效模式。描述符事件就绪后,无论用户有没有处理完数据,epoll都只会提醒一次,所以在处理时要获取完整数据,需要循环获取所有数据;代码实现(epoll-ET.c

    1.  
      //epoll-LT.c
    2.  
      //I/O复用:epoll() LT模式
    3.  
      //LT模式:描述符时间就绪后,如果用户没有处理完数据,epoll会反复提醒,直到处理完成
    4.  
       
    5.  
      #define _GNU_SOURCE
    6.  
       
    7.  
      #include <stdio.h>
    8.  
      #include <unistd.h>
    9.  
      #include <stdlib.h>
    10.  
      #include <string.h>
    11.  
      #include <assert.h>
    12.  
      #include <sys/socket.h>
    13.  
      #include <netinet/in.h>
    14.  
      #include <arpa/inet.h>
    15.  
      #include <pthread.h>
    16.  
      #include <sys/epoll.h>
    17.  
       
    18.  
      #define MAXFD 10
    19.  
      int create_socket();
    20.  
      void epoll_add(int epfd,int fd)
    21.  
      {
    22.  
      struct epoll_event ev;
    23.  
      ev.events = EPOLLIN; //LT模式
    24.  
      ev.data.fd = fd;
    25.  
       
    26.  
      if( epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev) == -1 )
    27.  
      {
    28.  
      perror("epoll_ctl error");
    29.  
      }
    30.  
      }
    31.  
       
    32.  
      void epoll_del(int epfd,int fd)
    33.  
      {
    34.  
      if( epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL) == -1 )
    35.  
      {
    36.  
      perror("epoll del erreo");
    37.  
      }
    38.  
      }
    39.  
      int main()
    40.  
      {
    41.  
      int sockfd = create_socket();
    42.  
      assert(sockfd != -1);
    43.  
       
    44.  
      int epfd = epoll_create(MAXFD);
    45.  
      assert(epfd != -1);
    46.  
       
    47.  
      epoll_add(epfd,sockfd);
    48.  
       
    49.  
      struct epoll_event events[MAXFD];
    50.  
      while (1)
    51.  
      {
    52.  
      int n = epoll_wait(epfd,events,MAXFD,5000);
    53.  
      if( n == -1 )
    54.  
      {
    55.  
      perror("epoll error");
    56.  
      }
    57.  
      else if(n == 0)
    58.  
      {
    59.  
      printf("time out ");
    60.  
      }
    61.  
      else
    62.  
      {
    63.  
      int i = 0;
    64.  
      for(;i<n;i++)
    65.  
      {
    66.  
      if(events[i].events & EPOLLIN)
    67.  
      {
    68.  
      if( events[i].data.fd == sockfd )
    69.  
      {
    70.  
      struct sockaddr_in caddr;
    71.  
      int len = sizeof(caddr);
    72.  
      int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
    73.  
      if ( c < 0 )
    74.  
      {
    75.  
      continue;
    76.  
      }
    77.  
      epoll_add(epfd,c);
    78.  
      printf("accept = %d ",c);
    79.  
      }
    80.  
      else
    81.  
      {
    82.  
      char buff[128] = {0};
    83.  
      int num = recv(events[i].data.fd,buff,1,0);
    84.  
      if( num <= 0)
    85.  
      {
    86.  
      epoll_del(epfd,events[i].data.fd);
    87.  
      close(events[i].data.fd);
    88.  
      printf("one client over ");
    89.  
       
    90.  
      }
    91.  
      else
    92.  
      {
    93.  
      printf("recv(%d):%s ",events[i].data.fd,buff);
    94.  
      send(events[i].data.fd,"ok",2,0);
    95.  
      }
    96.  
      }
    97.  
      }
    98.  
      }
    99.  
      }
    100.  
      }
    101.  
       
    102.  
      }
    103.  
       
    104.  
      int create_socket()
    105.  
      {
    106.  
      int sockfd = socket(AF_INET,SOCK_STREAM,0);
    107.  
      if(sockfd == -1)
    108.  
      {
    109.  
      return -1;
    110.  
      }
    111.  
       
    112.  
      struct sockaddr_in saddr;
    113.  
      memset(&saddr,0,sizeof(saddr));
    114.  
      saddr.sin_family = AF_INET;
    115.  
      saddr.sin_port = htons(6000);
    116.  
      saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    117.  
       
    118.  
      int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    119.  
      assert(res != -1);
    120.  
      listen(sockfd,5);
    121.  
      return sockfd;
    122.  
      }
    1.  
      //epoll-ET.c
    2.  
      //I/O复用:epoll() ET模式
    3.  
      //ET模式必须使用非阻塞模式
    4.  
       
    5.  
      #define _GNU_SOURCE
    6.  
       
    7.  
      #include <stdio.h>
    8.  
      #include <unistd.h>
    9.  
      #include <stdlib.h>
    10.  
      #include <string.h>
    11.  
      #include <assert.h>
    12.  
      #include <sys/socket.h>
    13.  
      #include <netinet/in.h>
    14.  
      #include <arpa/inet.h>
    15.  
      #include <pthread.h>
    16.  
      #include <sys/epoll.h>
    17.  
      #include <fcntl.h>
    18.  
       
    19.  
      #define MAXFD 10
    20.  
      int create_socket();
    21.  
      void setnonblock(int fd)
    22.  
      {
    23.  
      int oldflg = fcntl(fd,F_GETFL); //fcntl()可以设置非阻塞
    24.  
      int newflg = oldflg | O_NONBLOCK;
    25.  
       
    26.  
      if(fcntl(fd,F_SETFL,newflg) == -1)
    27.  
      {
    28.  
      perror("fcntl error ");
    29.  
      }
    30.  
      }
    31.  
      void epoll_add(int epfd,int fd)
    32.  
      {
    33.  
      struct epoll_event ev;
    34.  
      ev.events = EPOLLIN | EPOLLET; //ET模式
    35.  
      ev.data.fd = fd;
    36.  
       
    37.  
      setnonblock(fd);
    38.  
       
    39.  
      if( epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev) == -1 )
    40.  
      {
    41.  
      perror("epoll_ctl error");
    42.  
      }
    43.  
      }
    44.  
       
    45.  
      void epoll_del(int epfd,int fd)
    46.  
      {
    47.  
      if( epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL) == -1 )
    48.  
      {
    49.  
      perror("epoll del erreo");
    50.  
      }
    51.  
      }
    52.  
      int main()
    53.  
      {
    54.  
      int sockfd = create_socket();
    55.  
      assert(sockfd != -1);
    56.  
       
    57.  
      int epfd = epoll_create(MAXFD);
    58.  
      assert(epfd != -1);
    59.  
       
    60.  
      epoll_add(epfd,sockfd);
    61.  
       
    62.  
      struct epoll_event events[MAXFD];
    63.  
      while (1)
    64.  
      {
    65.  
      int n = epoll_wait(epfd,events,MAXFD,5000);
    66.  
      if( n == -1 )
    67.  
      {
    68.  
      perror("epoll error");
    69.  
      }
    70.  
      else if(n == 0)
    71.  
      {
    72.  
      printf("time out ");
    73.  
      }
    74.  
      else
    75.  
      {
    76.  
      int i = 0;
    77.  
      for(;i<n;i++)
    78.  
      {
    79.  
      int fd = events[i].data.fd;
    80.  
      if(events[i].events & EPOLLIN)
    81.  
      {
    82.  
      if( fd == sockfd )
    83.  
      {
    84.  
      struct sockaddr_in caddr;
    85.  
      int len = sizeof(caddr);
    86.  
      int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
    87.  
      if ( c < 0 )
    88.  
      {
    89.  
      continue;
    90.  
      }
    91.  
      epoll_add(epfd,c);
    92.  
      printf("accept = %d ",c);
    93.  
      }
    94.  
      else
    95.  
      {
    96.  
      while(1)
    97.  
      {
    98.  
      char buff[128] = {0};
    99.  
      int num = recv(fd,buff,1,0);
    100.  
      if( num == -1 )
    101.  
      {
    102.  
      send(fd,"ok",2,0);
    103.  
      break;
    104.  
      }
    105.  
      else if( num == 0 )
    106.  
      {
    107.  
      epoll_del(epfd,fd);
    108.  
      close(fd);
    109.  
      printf("one client over ");
    110.  
      break;
    111.  
      }
    112.  
      else
    113.  
      {
    114.  
      printf("buff(%d) = %s ",fd,buff);
    115.  
      }
    116.  
      }
    117.  
      }
    118.  
      }
    119.  
      }
    120.  
      }
    121.  
      }
    122.  
      }
    123.  
       
    124.  
      int create_socket()
    125.  
      {
    126.  
      int sockfd = socket(AF_INET,SOCK_STREAM,0);
    127.  
      if(sockfd == -1)
    128.  
      {
    129.  
      return -1;
    130.  
      }
    131.  
       
    132.  
      struct sockaddr_in saddr;
    133.  
      memset(&saddr,0,sizeof(saddr));
    134.  
      saddr.sin_family = AF_INET;
    135.  
      saddr.sin_port = htons(6000);
    136.  
      saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    137.  
       
    138.  
      int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    139.  
      assert(res != -1);
    140.  
      listen(sockfd,5);
    141.  
       
    142.  
      return sockfd;
    143.  
      }

    select、poll、epoll的区别以及epoll的两种模式(LT、ET)以及实现

  • 相关阅读:
    项目测试与部署
    使用技术及部分代码截选
    校园电子设备报修回收系统需求分析
    java lambda expression
    Domain logic approaches
    Spring AOP Capabilities ang goals
    CDI Features
    JAVA DESIGN PATTERN
    LDAP & Implementation
    spring ref &history&design philosophy
  • 原文地址:https://www.cnblogs.com/lyp1010/p/13841054.html
Copyright © 2011-2022 走看看