poll和epoll函数介绍及使用

poll和epoll函数介绍及使用

1.poll函数

  • 函数原型:

    int poll(struct pollfd* fds, nfds_t nfds, int timeout);
    
  • 参数:

    fds:监听的文件描述符数组

    struct pollfd{
    	int fd;          //待监听的文件描述符
    	short events;    //待监听的文件描述符对应的事件
        //取值 POLLIN、POLLOUT、POLLERR
        short revents;   //传入时给0,如果满足对应事件返回上述取值
    }
    

    nfds:监听数组的实际有效监听个数

    timeout:超时时长,单位为毫秒,0表示不阻塞,-1表示阻塞等待

    返回值:返回满足对应监听事件的文件描述符总个数

  • 优点:

    • 可以拓展监听上限,超出1024上限
    • 自带数据结构,可以将监听事件集合和返回事件集合分离。
  • 缺点:

    • 不能跨平台,只能在linux下使用
    • 无法直接定位满足监听事件的文件描述符,编码难度大

2.文件描述符上限修改

  • 查看一个进程可以打开的socket描述符上限

    cat /proc/sys/fs/file-max
    
  • 修改进程可以打开的socke描述符上限

    sudo vi /etc/security/limits.conf
    soft nofile 65536
    hard nofile 100000
    
  • 使用指令进行修改

    ulimit -n 20000
    

3.epoll相关函数

  • epoll_create函数

    • 功能:创建一个监听红黑树,并且返回红黑树的根节点
    • 原型:
    int epoll_create(int size);
    
    • 参数

      size:创建的红黑树的监听节点数量

    • 返回值:

      成功:指向新创建的红黑树的根节点fd

      失败:-1,设置errno

  • epoll_ctl函数

    • 原型:
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
    
    • 参数:

      epfd:epoll_create函数的返回值

      op:对该监听红黑树所做的操作

      • EPOLL_CTL_ADD 添加fd到监听红黑树
      • EPOLL_CTL_MOD 修改fd在监听红黑树上的监听事件
      • EPOLL_CTL_DEL 将一个fd从监听红黑树上取下(取消监听)

      fd:待监听的fd

      event:本质是结构体,成员变量中有联合体

      struct epoll_event{
      	uint32_t events;   //取值为EPOLLIN EPOLLOUT EPOLLERR
      	epoll_data_t data;
      }
      typedef union epoll_data{
          void* 	 ptr;
          int   	 fd;      //对应监听的fd
          uint32_t u32;
          uint64_t u64
      }
      
  • epoll_wait函数

    • 函数原型
    int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout)
    
    • 参数:

      epfd:epoll_create函数的返回值

      events:传入传出参数,传出满足监听条件的fd结构体

      maxevents:数组元素的总个数

      timeout:超时时长,单位为毫秒,0表示不阻塞,-1表示阻塞等待

    • 返回值:

      大于0:满足监听的总个数,可以作循环上限

      0:没有满足监听的fd

      -1:失败,设置errno

  • epoll的应用流程

    lfd = socket();       //创建套接字
    bind();               //绑定地址结构
    listen();             //设置监听上限
    fd epfd, allset;
    epfd = epoll_create(1024); //返回监听红黑树根
    //tep用于设置单个fd属性,ep是epoll_wait传出满足监听事件的数组
    struct epoll_event* temp, ep[1024];
    temp.events = EPOLLIN;
    temp.data.fd = lfd;
    epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &temp); //将lfd添加到监听红黑树上
    int retl;
    //循环监听
    while(1)
    {
        ret = epoll_wait(epfd, ep, 1024, -1);
        for(i = 0; i < ret; i++)
        {
            if(ep[i].data.fd == lfd)
            {
                //有新的客户端发起连接请求,lfd满足读事件
                cfd = accept();      
                temp.events = EPOLLIN;
    			temp.data.fd = cfd;
                //把建立连接的文件描述符放到监听红黑树上
                epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &temp); 
            }
            else   //有客户端写数据,要对数据进行处理
            {
                n = Read(ep[i].data.fd, buf, sizeof(buf));  //读取数据
                if(n == 0)
                {
                    //关闭套接字
                    close(ep[i].data.fd);
                    //关闭的fd从红黑树摘下
                    epoll_ctl(epfd, EPOLL_CTL_DEL, ep[i].data.fd, NULL); 
                }
                else if(n > 0)
                {
                    //对数据进行处理
                    //小写转大写并写回去
                    write(ep[i].data.fd, buf, n);
                }
            }
        }
    }
    
  • epoll事件模式

    • 边沿触发:缓冲区剩余未读完的数据不会导致epoll_wait返回,新的事件满足才会触发

      struct epoll_event event;
      event.events = EPOLLIN | EPOLLET;
      epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &event);
      int flag = fcntl(cfd, F_GETFL);
      fla |= O_NONBLOCK;
      fcntl(cfd, F_SETFL, flg);
      
    • 水平触发:缓冲区剩余未读完的数据会导致epoll_wait返回

  • 优缺点:优势在于高效并突破1024文件描述符,缺点在于不能跨平台只能在Linux上使用。

4.ET和LT

  • 概念:
    • **LT(level triggered)**是缺省的工作方式,同时支持阻塞和非阻塞模式的套接字。如果文件(比如socket套接字)中仍然有数据,内核还是会继续通知。这种模式编程错误可能性小,传统的select和poll都是这种模式的代表。
    • **ET(edge-triggered)**是高速工作方式,只支持非阻塞模式的套接字。必须对文件有I/O操作,即文件描述符从就绪变成非就绪的时候,内核才会发起通知。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值