select,poll,epoll的区别
单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当然可以更改数量
ulimit命令
语法格式:ulimit [参数]
常用参数:
-a 显示目前资源限制的设定
显示系统资源的设置:
ulimit -a
-d 程序数据节区的最大值,单位为KB
-t 指定CPU使用时间的上限,单位为秒
指定CPU使用时间的上限为2s :
ulimit -t 2
-u 用户最多可开启的程序数目
设置单一用户程序数目上限:
ulimit -u 500
-v 指定可使用的虚拟内存上限,单位为KB
指定可使用的虚拟内存上限为12800KB :
ulimit -v 12800
-n 修改每个进程可打开的文件数,缺省值是 1024
将每个进程可以打开的文件数目加大到4096:
ulimit -n 4096
但由于 select 采用轮询的方式扫描文件描述符,文件描述符数量越多,性能越差;
内核/用户空间内存拷贝问题, select 需要复制大量的句柄数据结构,产生巨大的开销; select 返回的是含有整个句柄的数组,应用程序需要遍历整个数组才能发现哪些句柄发生了
事件:
select的触发方式是水平触发,应用程序如果没有完成对一个已经就绪的文件描述符进行 IO ,那么之后再次 select 调用还是会将这些文件描述符通知进程。
相比于 select 模型,poll使用链表保存文件描述符,因此没有了监视文件数量的限制,但其他三个缺点依然存在。
拿 select 模型为例
假设我们的服务器需要支持100万的并发连接,则在_ FD _ SETSIZE 为1024的情况下,则我们至少需要开辟1k个进程才能实现100万的并发连接。
除了进程间上下文切换的时间消耗外,从内核/用户空间大量的无脑内存拷贝、数组轮询等,是系统难以承受的。因此,基于 select 模型的服务器程序,要达到10万级别的并发访间,是一个很难完成的任务。
由于 epoll的实现机制与 select / pol 机制完全不同,上面所说的 select 的缺点在 epoll 上不复存在。
epoll 通过在 linux 内核中申请一个简易的文件系统(文件系统一般用什么数据结构实现? 树)
把原先的 select / poll 调用分成了3个部分:
(1)调用 epoll _ create 建立一个 epoll 对象(在 epoll 文件系统中为这个句柄对象分配资源)
(2)调用 epoll _ ctl 向 epoll 对象中加这100万个连接的套接字
(3)调用 epol _ wait 收集发生的事件的连接
总结:
select 缺点:
单个进程能够监视的文件描述符的数量存在最大限制
文件描述符数量越多,性能越差;
内核/用户空间内存拷贝问题,产生巨大的开销
触发方式是水平触发
poll 缺点:
文件描述符数量越多,性能越差
内核/用户空间内存拷贝问题,产生巨大的开销
触发方式是水平触发
epoll :解决以上4个缺点