使用select/poll模型假设一台服务器需要支持100w的并发连接,在_FD_SETSIZE为1024时,则至少需要1k个进程
除了进程间的上下文切换的时间消耗外,从内核/用户空间,大量的无脑内存拷贝、数组轮询,是系统难以承受的。

epoll的呢,它没有单进程文件描述符限制,100w个客户端同时与一个服务器进程保持连接,而每一时刻,通常只有几百上千个TCP连接是活跃的

select/poll时,服务器进程每次都把100w个连接告诉操作系统(从用户态复制句柄数据结构到内核态),让操作系统去轮询是否有就绪事件发生
轮询完后,再将句柄数据复制到用户态,让服务器应用程序轮询处理已发生的事件,这一个过程消耗资源较大,因此,select/poll一般只能处理
几千的并发连接

epoll的设计和实现与select完全不同。epoll通过在Linux内核中申请一个简易的文件系统(文件系统一般用什么数据结构实现?B+树)。把原先的select/poll调用分成了3个部分:

1)调用epoll_create()建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源)

2)调用epoll_ctl向epoll对象中添加这100万个连接的套接字

3)调用epoll_wait收集发生的事件的连接

如此一来,要实现上面说是的场景,只需要在进程启动时建立一个epoll对象,然后在需要的时候向这个epoll对象中添加或者删除连接。同时,epoll_wait的效率也非常高,
因为调用epoll_wait时,并没有一股脑的向操作系统复制这100万个连接的句柄数据,内核也不需要去遍历全部的连接。

所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当相应的事件发生时会调用这个回调方法。这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双链表中
epoll的数据结构中,有一个rdlist,是系统发现的有事件的连接组成的双向链表,当应用程序调用epoll.wait时,内核会把发生的事件复制到用户态,同时
将事件数量返回给用户

内核态,linux系统最高权限,用户态,一般是最低权限,那么应用程序想调用一些高权限才能访问的设备时,需要切换到内核态,由内核去完成
用户态切换到内核态时,一般会伴随一些参数,传递给内核

参考博文:https://blog.csdn.net/davidsguo008/article/details/73556811

posted on 2018-06-04 20:11  j.liu windliu  阅读(165)  评论(0编辑  收藏  举报