IO多路复用之poll

IO多路复用之poll

poll函数接口:
#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

// pollfd结构
struct pollfd
{
    int fd;          /* file descriptor */
    short events;    /* requested events*/
    short revents;   /* returned events*/
};

参数说明:

  • fds是一个poll函数监听的结构列表。每个元素中,包含3部分的内容:文件描述符,监听的事件集合,返回的事件集合。
  • nfds表示fds数组的长度。
  • timeout表示poll函数的超时时间,单位是ms.

返回结果:

  • 返回值<0,表示出错;
  • 返回值=0,表示poll函数等待超时;
  • 返回值>0,表示poll由于监听的文件描述符就绪而返回。
poll就绪条件

同select

读就绪
  • socket 内核中,接收缓冲区中的字节数,大于等于低水位标记SO_RCVLOWAT(so_rcvlowat),此时可以无阻塞的读文件描述符,并且返回值大于0;
  • socket TCP通信中,对端关闭连接,此时对该socket读,则返回0;
  • 监听的socket上有新的连接请求;
  • socket上有未处理的错误。

    缓冲区设置的原因:减少访问IO的次数,从而提高效率(因为访问IO的成本远远高于访问内存的)

写就绪
  • socket 内核中,发送缓冲区中的可用字节数(发送缓冲区的空闲位置大小),大于等于低水位SO_RCVLOEAT,此时可以无阻塞的写,并且返回值大于0;
  • socket 的写操作被关闭(close或者shutdown)。对一个写操作被关闭的socket进行写操作,会触发SIGPIPE信号;
  • socket 使用非阻塞connect连接或失败之后;
  • socket 上有未读的错误。
异常就绪
  • socket 上收到带外数据。关于带外数据,和TCP紧急模式相关(TCP协议头中,有一个紧急指针的字段)。
poll 优点

不同于select使用3个位图来表示3个fdset的方式,poll使用一个pollfd的指针来实现。

  • pollfd结构包含了要监视的event和发生的event,将输入和输出分开了,所以接口使用更好用。
  • poll并没有最大数量的限制。
poll 缺点
  • 和select函数一样,poll返回后,需要轮询polled来获取就绪的文件描述符。
  • 每次调用poll都需要把大量的polled结构从用户态拷贝到内核态。甚至远远高于select的拷贝,比select的效率更低。
  • 和select函数一样,每次调用poll都需要再内核遍历传递进来的所有fd.
poll示例:使用poll来监控标准输入

用poll实现IO多路复用特点:

  • 将所有的等待过程交给poll;
  • 只要由文件描述符返回,就可以直接进行文件描述符的读写过程。

代码:

poll.c:

 1 #include <stdio.h>                                                                                                               
  2 #include <unistd.h>                                                                                                              
  3 #include <poll.h>                                                                                                                
  4                                                                                                                                  
  5 int main()                                                                                                                       
  6 {                                                                                                                                
  7   struct pollfd fds;                                                                                                             
  8   fds.fd = 0; // 表示标准输入                                                                                                    
  9   fds.events = POLLIN; // 表示要监控的是读状态                                                                                   
 10   int ret = poll(&fds, 1, -1); // timeout返回值是-1,表示阻塞式等待                                                              
 11   if(ret < 0)                                                                                                                    
 12   {                                                                                                                              
 13     perror("poll");                                                                                                              
 14     return 1;                                                                                                                    
 15   }                                                                                                                              
 16                                                                                                                                  
 17   char buf[1024] = {0};                                                                                                          
 18   ssize_t read_size = read(0, buf, sizeof(buf)-1);                                                                               
 19   if(read_size < 0)                                                                                                              
 20   {                                                                                                                              
 21     perror("read"); 
 22     return 1;                                                                                                                    
 23   }                                                                                                                              
 24   if(read_size == 0)                                                                                                             
 25   {                                                                                                                              
 26     printf("read done!\n");                                                                                                      
 27     return 0;                                                                                                                    
 28   }                                                                                                                              
 29   buf[read_size] = '\n';                                                                                                         
 30                                                                                                                                  
 31   printf("%s\n", buf);                                                                                                           
 32   return 0;                                                                                                                      
 33 }       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值