【UNIX】select、poll、epoll学习

三者都是UNIX下多路复用的内核接口,select是跨平台的接口,poll是systemV标准,epoll是linux专有的接口,基于poll改造而成。

select

函数原型:

int select (int n,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout);
  select通过系统调用监视多个文件描述符的数组,select返回后,就绪的文件描述符会被修改标志位,使得进程可以获得准备就绪的文件描述符并继续I/O操作。

select目前的优点就是几乎所有的系统都支持select,缺点是最大只能监听1024个文件描述符,想监听超过1024个文件描述符时需要手动修改FD_SETSIZE大小,但这样活造成网络I/O性能下降;或者创建多进程,每个进程监听1024个文件描述符,这样会导致程序复杂度增加。

select的第一个参数n需要程序员自己处理,n为所有集合中最大的文件描述符值+1;select的第二个参数readfds列举的文件描述符被监视是否有可供读取的数据;select的第三个参数writefds列举的文件描述符被监视是否写入完成而不阻塞;select的第三个参数exceptfds列举的文件描述符被监视是否异常或者无法控制的数据是否可用(这些状态仅用于套接字);当文件描述符列表设置为NULL时该类文件描述符不被监视。select的第四个参数timeout用于设置超时时长,当select经过了timeout时长后仍然没有可用的文件描述符也将返回;select的返回值代表了当前可用的文件描述符的数量,范围为0-1024,当超时返回时返回值为0,其他时候是1-1024区间的值。

struct timeval {

long tv_sec; /* seconds */
long tv_usec; /* 10E-6 second */

};

如果select的timeout参数不为NULL,即便没有文件描述符准备好I/O,也会在等待ty_sec秒和ty_usec微秒后select返回,timeout在不同系统中的处理是不同的,最好每次调用select前设置一次。

向select监视的文件描述符集合中添加或者删除文件描述符通常采用系统定义的宏进行

FD_ZERO:将集合清空

FD_SET:向集合中添加一个文件描述符

FD_CLR:从集合中删除一个文件描述符

FD_ISSET :指定的文件描述符是否在集合中

能够放进fd_set中的最大的文件描述符值是1024,这个值是由FD_SETSIZE决定的。

select调用成功后非NULL的文件描述符集合将被修改,集合中将只剩下准备好的文件描述符,通过FD_ISSET轮询所有集合确定准备好I/O的文件描述符。

select的缺点:在于维护的存储文件描述符的数据结构需要在内核空间和用户空间来回复制,随着文件描述符数量的增加,复制所花费的开销也线性增长; 由于网络延迟,很多socket会处于非活跃状态,但select也会对其进行一次扫描。这两个缺点导致select的效率随文件描述符数量降低,在处理大量fd非活跃的集合时效率降低。

select仅支持水平触发(Level Triggered):即一个fd被返回可用后,如果没有对该fd进行I/O操作,那么下次select返回时仍然报告该fdI/O可用。

poll

poll和select本质上类似,但不存在最大文件描述符数量的限制,poll和select存在一样的缺点:维护的文件描述符数据结构在内核空间和用户空间来回拷贝,效率随监视的文件描述符数量而下降。

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 */
};

poll中的每一个pollfd指明一个被监视的文件描述符,nfds指明最大监视的文件描述符数,timeout代表了超时时长,单位为毫秒。

pollfd结构体的fd是文件描述符;events是要监视的事件掩码;revents是被监视的文件描述符操作结果事件掩码,内核在返回时设置这个域。每一个events都可能在revents中被返回。

epoll

epoll是linux2.6以后出现的内核直接支持的方法,具有了select和poll的一切优点,被认为是linux2.6下最优秀的I/O就绪通知方式。

epoll可以支持水平触发(Level Triggered)和边缘触发(Edge Triggered,当文件描述符就绪时仅通知进程一次,即使进程没有对其进行I/O操作,以后也不会再通知),边缘触发方式适合高速I/O,但编程实现较为复杂。

epoll同样只告知那些准备就绪的文件描述符,当调用epoll_wait成功返回时,返回值代表准备就绪的文件描述符,此时epoll一个指定的数组中取出相应数量的文件描述符即可,epoll采用了文件映射技术(mmap),内核和用户态访问同一段内存,避免了文件描述符在内核和用户态之间的互相复制;epoll还采用了基于事件的就绪通知方式,epoll事先通过epoll_ctl注册一个文件描述符,一旦某个文件描述符就绪时,系统会采用类似于callback的机制迅速激活这个文件描述符,当进程调用epoll_wait便得到通知。

epoll的优点有可监视的文件描述符数量等于系统可打开的最大文件描述符;epoll的效率不随监视的文件描述符数量增加而线性下降;epoll通过文件映射减少了内核和用户态数据复制开销。

函数原型

int epoll_create(int size);

创建一个epoll句柄,指定要监听的文件描述符数量

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

对epoll句柄进行操作

epfd指定epoll句柄;

op为指定的操作EP_CTL_ADD(注册新的句柄到epoll);EP_CTL_MOD(修改已经注册的文件描述符的监听事件);EP_CTL_DEL(删除一个已经注册的fd)

fd为要注册的文件描述符

event为监听的事件

epoll_event结构如下:

struct epoll_event {

__uint32_t events; /*Epoll events*/

epoll_data_t data; /*User data variable*/

}

events可以用以下几个宏的集合

EPOLLIN:当前文件描述符可读

EPOLLOUT:当前文件描述符可以写

EPOLLPRI:当前文件描述符有紧急数据可以读(应该表示有带外数据到来)

EPOLLERR:当前文件描述符发生错误

EPOLLHUP:对应的文件描述符被挂断

EPOLLET:将EPOLL设置为边缘触发模式

EPOLLONESHOT:只监听一次事件,当完成一次监听以后还需要监听该描述符的话需要再次加入到EPOLL队列中。

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

等待事件的发生,类似select返回。

后记

本次学习笔记基于网络搜索,非原创,也没有用到select、poll、epoll,可以说从零开始学,难免有些浅薄,待以后有了实际经验会进行补充。

补充

IPC和select、poll、epoll能否同时使用?通常不可以,这会带来不少麻烦,因为IPC的实现方式并不是文件描述符,如果需要同时使用IPC和多路复用(select、poll、epoll),可以采用fork子进程,然后父进程和子进程采用IPC或管道通信,其中一个进程使用多路复用技术监控文件描述符。

多路复用技能着重处理的文件描述符是socket、管道、伪终端(pty)、终端设备(tty)等系统文件描述符,对普通文件描述符不起作用。

【UNIX】select、poll、epoll学习,布布扣,bubuko.com

时间: 2024-10-10 21:39:44

【UNIX】select、poll、epoll学习的相关文章

select,poll,epoll用法

http://blog.csdn.net/sunboy_2050/article/details/6126712 select用法 #include <sys/time.h>       #include <sys/types.h>       #include <unistd.h> #include <sys/select.h> int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exc

I/O多路复用之select,poll,epoll简介

一.select 1.起源 select最早于1983年出现在4.2BSD中(BSD是早期的UNIX版本的分支). 它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作. 2.select的优点 目前几乎在所有的平台上支持,具有良好的跨平台支持. 3.select的缺点 单个进程能够监视的文件描述符的数量存在最大限制.默认情况下,在Linux上单个进程能够打开的最

select/poll/epoll on serial port

In this article, I will use three asynchronous conferencing--select, poll and epoll on serial port to transmit data between PC and Raspberry pi. Outline Character device file of serial port Naive serial communication Asynchronous conferencing Select

Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select poll epoll udp组播 线程池

[本文谢绝转载原文来自http://990487026.blog.51cto.com] Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select  poll  epoll udp组播 线程池 TCP 11种状态理解: 1,客户端正常发起关闭请求 2,客户端与服务端同时发起关闭请求 3,FIN_WAIT1直接转变TIME_WAIT 4,客户端接收来自服务器的关闭连接请求 多路IO转接服务器: select模型 poll模型 epoll模型 udp组播模型 线

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selectors模块 # Python队列/RabbitMQ队列

1 # 进程/线程/协程 2 # IO:同步/异步/阻塞/非阻塞 3 # greenlet gevent 4 # 事件驱动与异步IO 5 # Select\Poll\Epoll异步IO 以及selectors模块 6 # Python队列/RabbitMQ队列 7 8 ############################################################################################## 9 1.什么是进程?进程和程序之间有什么

多进程、协程、事件驱动及select poll epoll

目录 -多线程使用场景 -多进程 --简单的一个多进程例子 --进程间数据的交互实现方法 ---通过Queues和Pipe可以实现进程间数据的传递,但是不能实现数据的共享 ---Queues ---Pipe ---通过Manager可以不同进程间实现数据的共享 --进程同步,即进程锁 --进程池 -协程 --先用yield实现简单的协程 --Greenlet --Gevent --用协程gevent写一个简单并发爬网页 -事件驱动 --IO多路复用 ---用户空间和内核空间 ---文件描述符fd

IO复用之select poll epoll的总结

I/O复用使得程序能够同时监听多个文件描述符,对于提高程序性能至关重要.I/O复用不仅仅在网络程序中使用,但是我接触到的例子中,TCP网络编程那块使用I/O复用比较多,例如,TCP服务器同时处理监听socket和连接socket. 在了解I/O复用之前,我们需要先了解几个概念. 1,同步I/O与异步I/O 2,LT(水平触发)和ET(边缘触发) POSIX把两个术语定义如下: 同步I/O:导致请求进程阻塞,直到I/O操作完成 异步I/O:  不导致请求进程阻塞 阻塞是进程在等待某种资源,但是不能

Linux下select&amp;poll&amp;epoll的实现原理(一)

最近简单看了一把Linux linux-3.10.25 kernel中select/poll/epoll这个几个IO事件检测API的实现.此处做一些记录.其基本的原理是相同的,流程如下 先依次调用fd对应的struct file.f_op->poll()方法(如果有提供实现的话),尝试检查每个提供待检测IO的fd是否已经有IO事件就绪 如果已经有IO事件就绪,则直接所收集到的IO事件返回,本次调用结束 如果暂时没有IO事件就绪,则根据所给定的超时参数,选择性地进入等待 如果超时参数指示不等待,则

转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】

下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理还是有必要的.下面记录下分别基于Select/Poll/Epoll的echo server实现.Python Select Server,可监控事件数量有限制: 1 2 3 4 5 6 7 8 9 10 11 12 13 14

Linux内核中网络数据包的接收-第二部分 select/poll/epoll

和前面文章的第一部分一样,这些文字是为了帮别人或者自己理清思路的,而不是所谓的源码分析,想分析源码的,还是直接debug源码最好,看任何文档以及书都是下策.因此这类帮人理清思路的文章尽可能的记成流水的方式,尽可能的简单明了. Linux 2.6+内核的wakeup callback机制 Linux 内核通过睡眠队列来组织所有等待某个事件的task,而wakeup机制则可以异步唤醒整个睡眠队列上的task,每一个睡眠队列上的节点都拥有一个 callback,wakeup逻辑在唤醒睡眠队列时,会遍历