epoll、cpoll、xpoll
I/O 多路复用是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程或线程不阻塞于某个特定的 I/O 系统调用。select(),poll(),epoll()都是I/O多路复用的机制。I/O多路复用通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪,就是这个文件描述符进行读写操作之前),能够通知程序进行相应的读写操作。但select(),poll(),epoll()本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
与多线程(TPC(Thread Per Connection)模型)和多进程(典型的Apache模型(Process Per Connection,简称PPC))相比,I/O 多路复用的最大优势是系统开销小,系统不需要建立新的进程或者线程,也不必维护这些线程和进程。
I/O多路复用
select?EPool?:
1、select:
1)FD_ZERO: void FD_ZERO(fd_set *fdset);清空文件描述符集合;
2)FD_SET: void FD_SET(int fd, fd_set *fdset); 将一个给定的文件描述符加入集合之中;
3)select:返回就绪描述符的个数
select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)
4)read/write;send/recv:处理事件
select轮询的管子(socket、文件描述符)数目有限,默认为1024,即使把他扩大到1000,效率也会非常差:
a)每次,用户空间到内核空间的拷贝,拷贝时间空间都是o(n);
b)o(n)轮询(内核空间)
c)内核到用户空间的再次拷贝
d)再次o(n)轮询(用户空间)
当然,如果管口比较少的时候,select还是有用的。
2、epoll:
1)epoll_create: int epoll_create(int size);创建一个epool的句柄,size用来告诉内核这个监听的数目一共有多大,这个参数是最大监听的fd+1的值。当创建好epoll句柄后,它会占用一个fd值,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽;
2)epoll_ctl: int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);epoll的事件注册函数,它不同于slect是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。第一个参数是epoll_create()的返回值,第二个参数表示动作,用三个宏来标识:
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD: 修改已经注册的fd的监听事件;
EPOLL_CTL_DEL: 从epfd中删除一个fd;
第三个参数是要监听的fd,第四个参数是告诉内核需要监听什么事,
3)epoll_wait: int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);等待事件发生,类似于select()的调用。参数events用来从内核得到事件的集合,maxevents告知内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定)。该函数返回需要处理的事件数目,如返回0表示已超时。
4)read/write; send/recv:
不限制可以监控的管子数目;一个进程所支持的FD上限是最大可以打开文件的数目,1G内存机器上限大约是10W。
常数级别:
a) 用户空间和内核使用mmap进行文件描述符的交流,省去拷贝;
b) 红黑树 插入时间o(lgn)
c) 就绪队列(callback)
epoll对比select的优点:
1) 针对select第一步的每次o(n)的拷贝,使用了mmap方法;
2) 针对内核o(n)的遍历,引入了两个结构,第一个数红黑树,每次只需要加入感兴趣的管子,不必拷贝所有的管子,而且插入删除的时间复杂度都是o(n);第二是引入了一个就绪队列,这个就绪对别的操作都是通过callback实现的,每当某个管子上注册的事件发生,就把这个管子放到就绪队列里,这个就绪队列里只有活跃的管子,可能是o(n)也可能是o(1);
xpool:领导者、跟随者模式;
epoll:生产者、消费者模式:
cpoll:类似epoll,但是没有红黑屋,不是主动询问,而是被动告知:
由主人去询问管子是否有需求。说白了就是通过select实现io多路复用,剩下的和xs_epoll是一样的。
apoll:给active的需求管子提供服务:
和epool基本是一致的,只不过由仆人做的2个工作中,主人主动承担了第一个工作:读管子;
参考资料epoll:http://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html
参考资料epoll:http://blog.csdn.net/lingfengtengfei/article/details/12398299
参考资料select:http://www.cnblogs.com/Anker/p/3258674.html