select 和 epoll 的区别

select 的工作原理:

在调用select的时候  会层层调用,一直调用到do_select(),在do_select函数里面有poll_wait函数:如果当前不可读,当前应用程序进程会睡眠在等待队列上(等待队列是驱动程序提供的,由poll_wait的参数传入),如果当前可读,就会唤醒等待队列上的应用程序进程。

poll的工作原理:

在调用poll的时候,会层层调用,一直调用到do_poll,在do_poll函数里面有poll_wait函数:如果当前不可读,那么当前进程会睡眠在等待队列上(等待队列是驱动程序提供的,由poll_wait的参数传入)。如果当前可读,就会唤醒等待队列上的应用程序进程。

 

select和poll的区别?

描述fd集合的方式不同,poll使用pollfd结构,select使用fd_set结构

同时poll在最大描述符上没有限制,因为它是基于链表的。

select/poll的缺点:

1.每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

2.同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

3.支持的文件描述符太小  默认是1024

 

epoll的工作原理:

首先调用epoll_create建立epoll对象,此时内核在内核态开始准备存储要控制的句柄的空间。

其次通过epoll_ctl函数可以将刚建立的socket加入到epoll中让其监控,或者把epoll正在监控的某个socket句柄移出epoll,不在让其监控。

最后在epoll_wait调用时,在给定的timeout时间内,当在监控的所有句柄中有时间发生时,就返回用户态的进程。

 

问题的引入:

当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,主要有以下几种解决方案:

1.使用多进程或者多线程,但是这种方法会造成程序的复杂,而且进程与线程的创建维护也需要很多的开销。

2.用一个进程,使用非阻塞的I/O读取数据,当一个I/O不可读的时候立刻返回,检查下一个是否可读,这种形式的循环为轮询(polling),这种方法比较浪费CPU时间,因为大多数时间是不可读,但是仍花费时间不断反复执行read系统调用。

3.异步I/O(asynchronous I/O),当一个描述符准备好的时候用一个信号告诉进程,每个信号对每个进程而言只有1个,如果使该信号对两个描述符都起作用,那么进程在收到信号后,将无法判断是哪个描述符准备好了,也就是说信号的数量远小于潜在的打开的文件描述符的数量。

4.一种较好的方式为I/O多路转接(I/O multiplexing)(貌似也翻译多路复用),先构造一张有关描述符的列表(epoll中为队列),然后调用一个函数(这个函数可以选用epoll和select),直到这些描述符中的一个准备好时函数返回,返回时告诉进程是哪个I/O就绪。select和epoll这两个机制都是多路I/O机制的解决方案。

 

select/poll和epoll的区别?

1.select的句柄数目受限,select最多同时监听1024个fd。而epoll没有,它的限制是最大的打开文件句柄数目。

2.epoll的最大好处是与fd总数无关,与活跃数有关。不会随着fd的数目增长而降低效率,在selec中采用轮询处理,采用的数据结构类似数组,epoll是维护一个队列,直接看队列是不是空就可以了。epoll只会对"活跃"的fd进行操作,这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。只有"活跃"的fd才会主动的去调用 callback函数(把这个句柄加入队列)。

3.使用mmap加速内核与用户空间的消息传递。在这点上,epoll是通过内核与用户空间mmap同一块内存实现的。

posted @ 2017-05-23 15:59  china_sdd  阅读(263)  评论(0编辑  收藏  举报