十一、I/O复用之poll

一、poll概述

poll是另一种I/O复用,和select类似,也是在指定事件内轮询一定数量的文件描述符,判断其中是否有就绪的。本质都是统一监听,如果任意一个文件描述符上有关注的事件发生。则这个文件描述符以及发生的事件通知给应用程序。但某些机制又比select优秀很多。

二、poll函数详解

poll的函数原型:

int poll(struct pollfd fds[],int len,int timeout);
          //成功返回就绪文件描述符个数,失败返回-1,0表示超时

参数:

1. struct pollfd fds[]参数:

Struct pollfd
{
   int fd;//用户设置关注的文件描述符(用户填充),不是二进制了,是int类型
   short events;//用户关注的事件类型(用户填充)
   short revents;//由内核填充,就绪的事件类型
}

在这里插入图片描述
所以我们每次调用poll之前要先定义这个结构体,并用用户事件描述符对fd,events进行初始化,返回时就绪事件就在revents里面存储。可以看到 用户初始描述符和内核返回的就绪描述符是分开的,所以不用每次初始化它,初始化一次就可。 但我们仍然不知道是哪几个描述符就绪,只知道有几个就绪,还是需要轮询查找判断。

2. int len参数

表示结构体的大小,所以可以看到poll没有空间限制,可以存放很多很多个,不像select只能存储1024个。
3. timeout参数

定时时间,在一定时间内没有检测到就绪事件,返回0,为NULL表示永久阻塞。

三、poll的事件类型

通过poll的函数原型我们可以知道poll有很多事件类型,不像select只有可读,可写,异常事件,我们将这些事件列举出来,并标注几个常用的,如下图:
在这里插入图片描述
我们圈起来的是比较常用的三个。POLLRDHUP是专门捕捉客户端断开异常的,我们在select时通过recv<=0来判断客户端是否关闭,在这专门提供了函数。

四、poll的特点

【1.优点】

  • 在pollfd结构体中我们可以明确的看到。poll的文件描述符是通过整型值去记录的。所以其能处理的文件描述符的个数就比select要大得多。而且是由用户自己指定的而select中的fd_set就只有系统内核提供的1024位。所以在应付大数目的文件描述符的时候相比于select速度更快。
  • 因为poll将用户关注的和内核填充的分开可以,用户关注的事件类型是不会变的,所以初始化一次就可以。
  • 相比于select关注的事件类型更多

【2.缺点】

  • 大量的pollfd类型的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义,效率低下。
  • 与select一样,poll返回后,需要轮询pollfd类型的数组来获取就绪的描述符。

五、poll的代码实现

我们实现一个简单的代码,它和select的实现差不多,但还是有区别如下:

  • select每次要初始化结构体,因为用户和内核共用一个空间。poll不用,一次初始化,每次只用对结构体中的fd,events成员进行一次初始化,记录用户事件描述符,有新连接,添加到结构体中,连接断开,从结构体中删除。内核返回的就绪事件在revents中放着。
  • select在处理事件时比较简单,只需要判断是连接(添加进去)还是数据连接(处理数据)。而poll比较复杂,它需要判断监听,数据。数据连接时需要判断三种情况:没有事件发生;客户端自动断开连接事件发生;可读事件发生。

那我们现在实现客户端连接服务器,发送数据,服务器收到给客户端回复ok,我们以程序流程图来说明整个逻辑思路:
在这里插入图片描述
我们就根据这个思路写出代码:
poll.c

# define  _GNU_SOURCE//用来引入客户端断开链接事件,要放到最上面
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h>
# include<string.h>
# include<assert.h>

# include<sys/types.h>
# include<sys/socket.h>
# include<arpa/inet.h>
# include<netinet/in.h>
# include<poll.h>

# define LEN 100

int InitSocket()
{
   
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1) return -1;
    struct sockaddr_in ser;
    memset
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值