简单理解poll

前期知识:

在开始接触select之前,你需要先对IO的同步,异步,阻塞,非阻塞有个基本的了解,知道什么是IO多路复用。下面这篇文章可以帮助你快速区分这几种模型:IO - 同步,异步,阻塞,非阻塞 (亡羊补牢篇).


poll的系统调用:

poll系统调用和select类似,也是在指定时间内轮询一定数量的文件描述符,以测试其中是否有就绪者。


poll的函数格式:

#include <poll.h>
int poll (struct pollfd* fds,nfds_t nfds,int timeout);
  1. fds参数时一个pollfd结构类型的数组,它指定所有我们感兴趣的文件描述符上发送的可读、可写和异常等事件。

pollfd结构体的定义:

struct pollfd
{
	int    fd;     /* 文件描述符 */
	short  events; /* 注册的事件 */
	short  revents;/* 实际发生的事件,由内核填充 */
}

成员变量说明:
(1) fd:指定文件描述符

(2) events:告诉poll监听fd上的哪些事件,它是一系列事件的按位或;

(3) revents:由内核修改,以通知应用程序fd上实际发生了哪些事件。

  1. nfds参数指定被监听事件集合fds的大小。其类型nfds_t的定义如下:
typedef unsigned long int nfds_t;
  1. timeout参数指定poll的超时值,单位是毫秒。当timeout为 -1时,poll调用将永远阻塞,直到某个事件发生;当timeout为0时,poll调用将立即返回。

poll的事件类型

事件描述是否可作为输入是否可作为输出
POLLIN数据(包括普通数据和优先数据)可读
POLLRDNORM普通数据可读
POLLRDBAND优先带数据可读(Linux不支持)
POLLPRI高优先级数据可读,比如TCP带外数据
POLLOUT数据(包括普通数据和优先数据)可写
POLLWRNORM普通数据可写
POLLWRBAND优先级数据可写
POLLRDHUPTCP链接被对方关闭,或者对方关闭写操作。它由GNU引入
POLLERR错误
POLLHUP挂起
POLLNVAL文件描述符没有打开

poll的文件描述符就绪条件:

读就绪条件:

	1. socket内核接收缓存区中的字节数大于或等于其低水位标记SO_RCVLOWAT。此时我们可以无阻塞地读该socket,
并且读操作返回的字节数大于0.
	2.socket通信的对方关闭连接。此时对该socket的读操作将返回 0.
	3.监听socket上有新的连接请求。		
	4.socket上有未处理的错误。

写就绪条件:

	1.socket内核发生缓存区中的可用字节数大于或等于其低水位标记SO_SNDLOWAT。此时我们可以无阻塞地写该socket,
并且写操作返回的字节数大于0.
	2.socket的写操作被关闭,	对一个写操作被关闭的socket进行写操作, 会触发 SIGPIPE信号;
	3.socket使⽤非阻塞connect连接成功或失败之后;
	4.socket上有未读取的错误;

异常错误处理:

socket上接收到带外数据

poll函数示例

使用poll函数监控标准输入:
用poll监控标准输入是因为当没有输入的时候,进程就一直处于阻塞状态,当有数据输入时时间就立即就绪,如果监听标准输出,由于写缓冲区比较大,可能一直处于就绪状态,不利于观察。

#include<stdio.h>
#include<unistd.h>
#include<poll.h>

int main()
{
	struct pollfd poll_fd;
	poll_fd.fd = 0;
	poll_fd.events = POLLIN;

	for (;;)
	{
		int ret = poll(&poll_fd, 1, 2000);
		if (ret < 0)
		{
			perror("poll");
			continue;
		}
		if (ret == 0)
		{
			printf("poll timeout!\n");
			continue;
		}
		if (poll_fd.revents == POLLIN)
		{
			char buf[1024];
			read(0, buf, sizeof(buf) - 1);
			printf("sdin:%s", buf);
		}
	}
}

运行结果:
当没有输入时,进程处于阻塞状态(每两秒输出一条poll timeout语句):
在这里插入图片描述
当有输入时,系统会告诉用户事件就绪,进行输入工作,即有输入时就打印到屏幕上:
在这里插入图片描述


poll函数的优缺点

通过poll函数的结构以及小测试程序的编写,我们不难发现poll函数的一些特点:

1、优点
(1)poll() 不要求开发者计算最大文件描述符加一的大小。
(2)poll() 在应付大数目的文件描述符的时候速度更快,相比于select。
(3)它没有最大连接数的限制,原因是它是基于链表来存储的。
(4)在调用函数时,只需要对参数进行一次设置就好了

2、缺点
(1)大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。
(2)与select一样,poll返回后,需要轮询pollfd来获取就绪的描述符,这样会使性能下降
(3)同时连接的大量客户端在一时刻可能只有很少的就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降

参考资料:Linux高性能服务器编程,poll方法的基本概念

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值