Linux的三种I/O复用方式——poll

I/O复用函数

select
poll
epoll

接下来我们分三次进行介绍I/O复用

poll

poll的原型是

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

比起select更加简洁了一些,事件不再由内核在线修改,而是存入系统提供的结构体中,将文件描述符和从内核拷贝而来的改变数据划分开,不需要每次重置poll,比select聪明了一些,以下是struct pollfd的内容

struct pollfd
{	int fd//关注的文件描述符
	short events;//fd将会发生什么事情,或者期望看到的事情,写在这里
	short revents;//由内核修改,返回此文件描述符发生的事件类型(必须是events指定的关注的事件)
}

ndfs:传入的结构体数组长度,因为此时的*fds会退化为指针,更准确的来说,ndfs的类型是ndfs_t是无类型的long int数据
timeout:等同于select中timeout的效果
由于pollfd的特性,我么能关注的事件类型就更多了,如下图(来自Linux高性能服务器编程)
Linux的三种I/O复用方式——poll_第1张图片
使用前,在文件一开始加入#define _GNU_SOURCE保证POLLRDHUP正常使用,上图中POLLRDNORM,POLLRDBAND,POLLWRNORM,POLLWRBANDLinux并不是完全支持,这实际上是POLLIN和POLLOUT更加细化的事件
其中POLLIN和POLLRDHUP事件有一定的关联,如果POLLRDHUP事件触发,则POLLIN也会被触发,但是反过来不一定。在处理响应事件时要注意判断到底是POLLIN还是POLLRDHUP。
也就是说POLLRDHUP嵌套在POLLIN事件里,先判断范围大的然后判断范围小的,逐步细分。

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 

#define FDMAXNUM 100

void Init_Fds(struct pollfd *fds)
{
	int i = 0;
	for (; i 

poll的特点:

  1. 将用户关注的事件与内核修改的就绪事件分隔开,每次调用poll不需要重新设置
  2. poll通过int类型记录文件描述符,文件描述符的取值范围扩大到系统最大限制65535
  3. 用户关注的所有文件描述符通过fds指向的用户数组来记录,则可以关注的文件描述符的个数由用户指定,能扩大到系统最大限制

poll存在的问题:

  1. 返回值返回就绪的文件描述符个数,poll也仅仅是在fds指向的数组元素中标记出那个文件描述符就绪,用户探测的时候依然需要for循环,时间复杂度依旧是O(n)
  2. 在内核中依旧是轮询方式处理

你可能感兴趣的:(学习心得)