I/O复用 poll简介
1、基本概念
poll起源于SVR3,开始时局限于流设备,在SVR4时取消了此限制,允许poll工作在任何描述符上,但涉及到流设备时,它还提供了附加信息。
poll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制。poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
2.poll函数
# include <poll.h>
int poll ( struct pollfd * fds, unsigned int nfds, int timeout); 返回:准备好的描述字个数,0-超时,1-出错。
参数说明
- fds:存放需要被检测状态的Socket描述符;与select不同(select函数在调用之后,会清空检测socket描述符的数组),每当调用这个函数之后,系统不会清空这个数组,而是将有状态变化的描述符结构的revents变量状态变化,操作起来比较方便;
- nfds:用于标记数组fds中的struct pollfd结构元素的总数量;
- timeout:poll函数调用阻塞的时间,单位是MS(毫秒),无论I/O是否准备好,poll都会返回;timeout指定为负数值表示无限超时,使poll()一直挂起直到一个指定事件发生;
timeout为指示poll调用立即返回并列出准备好I/O的文件描述符,但并不等待其它的事件。这种情况下,poll()就像它的名字那样,一旦选举出来,立即返回。
返回值和错误代码
成功时,poll()返回结构体中revents域不为0的文件描述符个数;如果在超时前没有任何事件发生,poll()返回0;失败时,poll()返回-1,并设置errno为下列值之一:
EBADF 一个或多个结构体中指定的文件描述符无效。
EFAULTfds 指针指向的地址超出进程的地址空间。
EINTR 请求的事件之前产生一个信号,调用可以重新发起。
EINVALnfds 参数超出PLIMIT_NOFILE值。
ENOMEM 可用内存不足,无法完成请求。
pollfd结构体定义如下,【在源码文件poll.h文件中】
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 等待的事件 */
short revents; /* 实际发生了的事件 */
} ;
每一个pollfd结构体指定了一个被监视的文件描述符,可以传递多个结构体,指示poll()监视多个文件描述符。每个结构体的events域是监视该文件描述符的事件掩码,由用户来设置这个域。revents域是文件描述符的操作结果事件掩码,内核在调用返回时设置这个 域。events域中请求的任何事件都可能在revents域中返回。合法的事件如下:
POLLIN 普通或优先级带数据可读。
POLLRDNORM 有普通数据可读。
POLLRDBAND 优先级带数据可读。
POLLPRI 高优先级数据可读。
POLLOUT 普通数据可写,写数据不会导致阻塞。
POLLWRNORM 普通数据可写,写普通数据不会导致阻塞。
POLLWRBAND 优先级带数据可写,写优先数据不会导致阻塞。
POLLMSGSIGPOLL 消息可用。
此外,revents域中还可能返回下列事件:
POLLER 指定的文件描述符发生错误。
POLLHUP 指定的文件描述符挂起事件。
POLLNVAL 描述字不是一个打开的文件。
3.poll应用实例
服务器端代码:
/* include fig01 */
#include "unp.h"
#include <limits.h> /* for OPEN_MAX */ int
main(int argc, char **argv)
{
int i, maxi, listenfd, connfd, sockfd;
int nready;
ssize_t n;
char buf[MAXLINE];
socklen_t clilen;
struct pollfd client[OPEN_MAX];
struct sockaddr_in cliaddr, servaddr; listenfd = Socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); client[].fd = listenfd;
client[].events = POLLRDNORM;
for (i = ; i < OPEN_MAX; i++)
client[i].fd = -; /* -1 indicates available entry */
maxi = ; /* max index into client[] array */
/* end fig01 */ /* include fig02 */
for ( ; ; ) {
nready = Poll(client, maxi+, INFTIM); if (client[].revents & POLLRDNORM) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
#ifdef NOTDEF
printf("new client: %s\n", Sock_ntop((SA *) &cliaddr, clilen));
#endif for (i = ; i < OPEN_MAX; i++)
if (client[i].fd < ) {
client[i].fd = connfd; /* save descriptor */
break;
}
if (i == OPEN_MAX)
err_quit("too many clients"); client[i].events = POLLRDNORM;
if (i > maxi)
maxi = i; /* max index in client[] array */ if (--nready <= )
continue; /* no more readable descriptors */
} for (i = ; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i].fd) < )
continue;
if (client[i].revents & (POLLRDNORM | POLLERR)) {
if ( (n = read(sockfd, buf, MAXLINE)) < ) {
if (errno == ECONNRESET) {
/*4connection reset by client */
#ifdef NOTDEF
printf("client[%d] aborted connection\n", i);
#endif
Close(sockfd);
client[i].fd = -;
} else
err_sys("read error");
} else if (n == ) {
/*4connection closed by client */
#ifdef NOTDEF
printf("client[%d] closed connection\n", i);
#endif
Close(sockfd);
client[i].fd = -;
} else
Writen(sockfd, buf, n); if (--nready <= )
break; /* no more readable descriptors */
}
}
}
}
/* end fig02 */
I/O复用 poll简介的更多相关文章
- Linux中的IO复用接口简介(文件监视?)
I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...
- I/O复用----poll
2018-08-01 (星期三)poll(): #include <sys/poll.h> int poll (struct pollfd *fd, unsigned int nfds, ...
- IO复用——poll系统调用
1.poll函数 #include<poll.h> int poll(struct pollfd* fds, nfds_t ndfs, int timeout) poll函数在一定的时间内 ...
- 高级IO复用应用:聊天室程序
简单的聊天室程序:客户端从标准输入输入数据后发送给服务端,服务端将用户发送来的数据转发给其它用户.这里采用IO复用poll技术.客户端采用了splice零拷贝.服务端采用了空间换时间(分配超大的用户数 ...
- 网络编程-I/O复用
I/O模型 Unix下可用的I/O模型有五种: 阻塞式I/O 非阻塞式I/O I/O复用(select和poll.epoll) 信号驱动式I/O(SIGIO) 异步I/O(POSIX的aio_系列函数 ...
- 阻塞与非阻塞、同步与异步 I/O模型
I/O模型 Linux 下的五种I/O模型 阻塞I/O(blocking I/O) 非阻塞I/O (nonblocking I/O) I/O复用(select 和poll) (I/O multiple ...
- 【转】FFmpeg 基本用法
FFmpeg FFmpeg 基本用法 本课要解决的问题 1.FFmpeg的转码流程是什么? 2.常见的视频格式包含哪些内容吗? 3.如何把这些内容从视频文件中抽取出来? 4.如何从一种格式转换为另一种 ...
- ffmpeg基本用法
FFmpeg FFmpeg 基本用法 本课要解决的问题 1.FFmpeg的转码流程是什么? 2.常见的视频格式包含哪些内容吗? 3.如何把这些内容从视频文件中抽取出来? 4.如何从一种格式转换为另一种 ...
- 黄聪:ffmpeg基本用法(转)
FFmpeg FFmpeg 基本用法 本课要解决的问题 1.FFmpeg的转码流程是什么? 2.常见的视频格式包含哪些内容吗? 3.如何把这些内容从视频文件中抽取出来? 4.如何从一种格式转换为另一种 ...
随机推荐
- delphi遍历指定目录下指定类型文件的函数
遍历指定目录下指定类型文件的函数// ================================================================// 遍历某个文件夹下某种文件,/ ...
- scrapy原理
scarpy据说是目前最强大的爬虫框架,没有之一.就是这么自信. 官网都是这么说的. An open source and collaborative framework for extracting ...
- lambda表达式学习例子
https://www.cnblogs.com/franson-2016/p/5593080.html https://www.cnblogs.com/fx-blog/p/11745205.html ...
- jquery与其他js冲突
var $j=JQuery.noConflict(); $j('#msg').hide();//此处$j就代表JQuery //重命名以下,把$改为$j
- vi 编辑器使用指南
一.Unix编辑器概述编辑器是使用计算机的重要工具之一,在各种操作系统中,编辑器都是必不可少的部件.Unix及其相似的ix操作系统系列中,为方便各种用户在各个不同的环境中使用,提供了一系列的ex编辑器 ...
- Webx.0-Web4.0:Web4.0
ylbtech-Webx.0-Web4.0:Web4.0 Web系统是人类迄今最伟大的发明之一,也是计算机影响人类最深远的表现. 1.返回顶部 1. Web系统是人类迄今最伟大的发明之一,也是计算机影 ...
- idea 查看字节码 bytecode插件 (jclasslib Bytecode Viewer、ASM Bytecode Viewer )
文章目录 jclasslib Bytecode Viewer ASM Bytecode Viewer jclasslib Bytecode Viewer 然后重启idea===>重新编译(构建项 ...
- Hexo next博客的pjax一个Bug引发的关于pjax用法的小技巧-----pjax后图片点击放大的js失效
文章目录 广告: 背景 发现 解决 get技能 广告: 本人博客地址:https://mmmmmm.me 源码:https://github.com/dataiyangu/dataiyangu.git ...
- Spring 源码学习——Aop
Spring 源码学习--Aop 什么是 AOP 以下是百度百科的解释:AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程通过预编译的方式和运行期动态代理实 ...
- JOGL教程
本章介绍了OpenGL,Java OpenGL绑定(GL4java,LWJGL,JOGL)和JOGL比其他的OpenGL的优点. Java支持OpenGL(JOGL)是近期在Java OpenGL图形 ...