select、poll、epoll使用小结
转载:http://blog.csdn.net/kkxgx/article/details/7717125
Linux上可以使用不同的I/O模型,我们可以通过下图了解常用的I/O模型:同步和异步模型,以及阻塞和非阻塞模型,本文主要分析其中的异步阻塞模型。
一、select使用
这个模型中配置的是非阻塞I/O,然后使用阻塞select系统调用来确定一个I/O描述符何时有操作。使用select调用可以为多个描述符提供通知,对于每个提示符,我们可以请求描述符的可写,可读以及是否发生错误。异步阻塞I/O的系统流程如下图所示:
使用select常用的几个函数如下:
- FD_ZERO(int fd, fd_set* fds)
- FD_SET(int fd, fd_set* fds)
- FD_ISSET(int fd, fd_set* fds)
- FD_CLR(int fd, fd_set* fds)
- int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
fd_set类型可以简单的理解为按bit位标记句柄的队列。具体的置位、验证可以使用FD_SET,FD_ISSET等宏实现。在select函数中,readfds、writefds和exceptfds同时作为输入参数和输出参数,如果readfds标记了一个位置,则,select将检测到该标记位可读。timeout为设置的超时时间。
下面我们来看如何使用select:
- SOCKADDR_IN addrSrv;
- int reuse = 1;
- SOCKET sockSrv,connsock;
- SOCKADDR_IN addrClient;
- pool pool;
- int len=sizeof(SOCKADDR);
- /*创建TCP*/
- sockSrv=socket(AF_INET,SOCK_STREAM,0);
- /*地址、端口的绑定*/
- addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
- addrSrv.sin_family=AF_INET;
- addrSrv.sin_port=htons(port);
- if(bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))<0)
- {
- fprintf(stderr,"Failed to bind");
- return ;
- }
- if(listen(sockSrv,5)<0)
- {
- fprintf(stderr,"Failed to listen socket");
- return ;
- }
- setsockopt(sockSrv,SOL_SOCKET,SO_REUSEADDR,(const char*)&reuse,sizeof(reuse));
- init_pool(sockSrv,&pool);
- while(1)
- {
- /*通过selete设置为异步模式*/
- pool.ready_set=pool.read_set;
- pool.nready=select(pool.maxfd+1,&pool.ready_set,NULL,NULL,NULL);
- if(FD_ISSET(sockSrv,&pool.ready_set))
- {
- connsock=accept(sockSrv,(SOCKADDR *)&addrClient,&len);
- //loadDeal()/*连接处理*/
- //printf("test\n");
- add_client(connsock,&pool);//添加到连接池
- }
- /*检查是否有事件发生*/
- check_client(&pool);
- }
上面是一个服务器代码的关键部分,设置为异步的模式,然后接受到连接将其添加到连接池中。监听描述符上使用select,接受客户端的连接请求,在check_client函数中,遍历连接池中的描述符,检查是否有事件发生。
二、poll使用
poll函数类似于select,但是其调用形式不同。poll不是为每个条件构造一个描述符集,而是构造一个pollfd结构体数组,每个数组元素指定一个描述符标号及其所关心的条件。定义如下:
- #include <sys/poll.h>
- int poll (struct pollfd *fds, unsigned int nfds, int timeout);
- struct pollfd {
- int fd; /* file descriptor */
- short events; /* requested events to watch */
- short revents; /* returned events witnessed */
- };
每个结构体的events域是由用户来设置,告诉内核我们关注的是什么,而revents域是返回时内核设置的,以说明对该描述符发生了什么事件。这点与select不同,select修改其参数以指示哪一个描述符准备好了。在《unix环境高级编程》中有一张events取值的表,如下:
POLLIN :可读除高优级外的数据,不阻塞
POLLRDNORM:可读普通数据,不阻塞
POLLRDBAND:可读O优先数据,不阻塞
POLLPRI:可读高优先数据,不阻塞
POLLOUT :可写普数据,不阻塞
POLLWRNORM:与POLLOUT相同
POLLWRBAND:写非0优先数据,不阻塞
其次revents还有下面取值
POLLERR :已出错
POLLHUP:已挂起,当以描述符被挂起后,就不能再写向该描述符,但是仍可以从该描述符读取到数据。
POLLNVAL:此描述符并不引用一打开文件
对poll函数,nfds表示fds中的元素数,timeout为超时设置,单位为毫秒若为0,表示不等待,为-1表示描述符中一个已经准备好或捕捉到一个信号返回,大于0表示描述符准备好,或超时返回。函数返回值返回值若为0,表示没有事件发生,-1表示错误,并设置errno,大于0表示有几个描述符有事件。
poll的使用和select基本类似。在此不再介绍。poll相对于是select的优势是监听的描述符数量没有限制。
三、epoll学习
epoll有两种模式,Edge Triggered(简称ET) 和 Level Triggered(简称LT).在采用这两种模式时要注意的是,如果采用ET模式,那么仅当状态发生变化时才会通知,而采用LT模式类似于原来的select/poll操作,只要还有没有处理的事件就会一直通知.
1)epoll数据结构介绍:
- typedef union epoll_data
- {
- void *ptr;
- int fd;
- __uint32_t u32;
- __uint64_t u64;
- } epoll_data_t;
- struct epoll_event
- {
- __uint32_t events; /* Epoll events */
- epoll_data_t data; /* User data variable */
- };
常见的事件如下:
EPOLLIN:表示对描述符的可以读
EPOLLOUT:表示对描述符的可以写
EPOLLPRI:表示对描述符的有紧急数据可以读
EPOLLERR:发生错误
EPOLLHUP:挂起
EPOLLET:边缘触发
EPOLLONESHOT:一次性使用,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
2)函数介绍
epoll的三个函数
- int epoll_creae(int size);
功能:该函数生成一个epoll专用的文件描述符
参数:size为epoll上能关注的最大描述符数
- int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:用于控制某个epoll文件描述符时间,可以注册、修改、删除
参数:epfd由epoll_create生成的epoll专用描述符
op操作:EPOLL_CTL_ADD 注册 EPOLL_CTL_MOD修改 EPOLL_DEL删除
fd:关联的文件描述符
evnet告诉内核要监听什么事件
- int epoll_wait(int epfd,struct epoll_event*events,int maxevents,int timeout);
功能:该函数等待i/o事件的发生。
参数:epfd要检测的句柄
events:用于回传待处理时间的数组
maxevents:告诉内核这个events有多大,不能超过之前的size
timeout:为超时时间
使用方法参考:https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/epoll-example.c
本文参考:https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/
http://www.ibm.com/developerworks/cn/linux/l-cn-edntwk/index.html?ca=drs-
http://www.ibm.com/developerworks/cn/linux/l-async/
select、poll、epoll使用小结相关推荐
- select poll epoll 高效IO 多路转接
目录 五种常见IO模型 高效IO的概念 阻塞 vs 非阻塞 非阻塞IO fcntl函数 I/O多路转接之select 初识select select函数原型 select操作接口 tcp_server ...
- java nio原理 epoll_多路复用 Select Poll Epoll 的实现原理(BIO与NIO)
BIO blocking阻塞的意思,当我们在后端开发使用的时候,accetp 事件会阻塞主线程. 当accept事件执行的时候,客户的会和服务建立一个socket 连接.一般后端就会开启一个线程执行后 ...
- Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)
一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 1 简单的启动线程语法 2 def run(na ...
- python3 异步 非阻塞 IO多路复用 select poll epoll 使用
有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理还是有必要的. 下面记录下分别基于Select/Poll/Epoll的echo ser ...
- select,poll,epoll区别面试常问
select,poll,epoll区别: select优点 1)select()的可移植性更好,在某些Unix系统上不支持poll() 2)select() 对于超时值提供了更好的精度:微秒,而pol ...
- IO模型(select, poll, epoll的区别和原理)
参考<unix网络编程> 参考http://blog.csdn.net/blueboy2000/article/details/4485874 参考http://blog.csdn.net ...
- select/poll/epoll 与 /dev/poll
select/poll 这两种实际上差不多,都是把一组fd传送给kernal,然后返回一个就绪fd的数量,然后开始遍历所有的fd,找到那些可读或者可写的. 区别在于,poll相比select来说,传送 ...
- select poll epoll IO操作多路复用及猴子补丁
一:select(能监控数量有限,不能告诉用户程序具体那个连接有数据) select目前几乎所有的平台都支持,其良好的跨平台支持也是一个优点 select的缺点在于单个进程能够监控的文件描述的数量存在 ...
- IO多路复用select/poll/epoll详解以及在Python中的应用
IO multiplexing(IO多路复用) IO多路复用,有些地方称之为event driven IO(事件驱动IO). 它的好处在于单个进程可以处理多个网络IO请求.select/epoll这两 ...
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用
来源:http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理 ...
最新文章
- 只有14秒,假老黄才是假的!黄仁勋没有骗了全世界,英伟达「元宇宙」验明正身...
- 高并发核心Selector详解
- 关于分布式计算的一些概念
- 去重除了indexOf的其他方法(使用对象Key的方法)及统计重复次数
- 力扣1512.好数对的数目
- 小程序初始化服务器数据,微信小程序 项目实战(一)生命周期 配置服务器信息 splash启动页...
- jQuery-1.9.1源码分析系列(十) 事件系统——事件包装
- Django官方文档翻译——Django中的用户身份验证(User authentication in Django)
- Mac 查找本机的ip
- 点击vue页面链接打开本地exe文件
- 13-[LVI-SAM]visual_odometry_初探
- html怎么把图片左移_css如何向左移动图片
- 优雅的创建一个相册管理类(兼容AssetsLibrary和PhotoKit)
- 在ARM板上运行Qt程序
- Test类中的@testSetup标注 测试环境数据准备
- Oracle FND - 用户API fnd_user_pkg的常用用法
- XShell下载安装并连接阿里云
- 聚观早报 | 百度文心一言被用户挤爆;贝莱德准备竞购瑞信
- 解决antimalware service executable程序占用CPU过高(有效)
- DNS域名解析自制笔记
热门文章
- SpringMVC整合MongoDB
- gl.vertexAtteib3f P42 讲数据传给location参数指定的attribute变量
- dorado开发模式下实现动态查询
- 1704:baoge的洗漱难题[黄]
- HDOJ 1896 Stones 解题报告
- 媒资管理系统的应用与发展
- java做的一个将中文转换成Unicode码的工具类【转载】做个标记,明天研究下
- suse10 linux安装,SuSE10.2 安装手记
- k8s源码分析 pdf_rook源码分析之一:rook架构解析
- yolov4Linux,基于Darknet的YOLOv4目标检测