epoll特点总结

(170) 2024-03-18 18:01:01

问题:epollpoll、select之类的区别,为何引入。


首先看其他模型的缺点:

2.1 PPC/TPC模型

这两个模型就是有个连接来了就给分配个进程/线程,前者肯定更费资源了,因为这么多进程/线程不是吃素的,都要时间和空间,开销大,所以并发只有几百?(也没说epoll是如何分配的?)

 

Epoll总结起来就三点!?四点?


一、epoll只管遍历活跃的FD,跟总连接数无关!

也就是说那两个得遍历所有,和连接数有关!Epoll也遍历,但是只遍历活跃的所以效率高。(强调实际网络环境,网络延时,实际同时交互的有限)

获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。但是,如何确定“活跃”?

(“活跃”怎么区分?其他的难道就是不管死活一直存在?好像也是,比如对方没send而你提前listen还是accept()来着?那就一直等待,所以可能是这种忙等机制)

“活跃”的区分——回调机制:

这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数,其他idle状态socket则不会,在这点上,epoll实现了一个"伪"AIO,因为这时候推动力在Linux内核

(所以不用自己筛选了,不用选择到底谁是活跃的了,是被动式的。)


二、epoll的高并发,没有最大连接数限制。

Epoll没有最大并发连接的限制,上限是最大可以打开文件的数目,这个数字一般远大于2048, 一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max察看。1G内存大概是10万?我这81万是8G内存?

 epoll特点总结 (https://mushiming.com/)  第1张

32位机器,8G内存可以看到?!!!如何寻址?

32linux不打开PAE,则最多只能识别出4GB内存,若打开PAE,则最多可以识别出64GB内存。但是 32位系统下的进程一次最多只能寻址4GB的空间。64linux则没有32位系统的限制。因此对于内存大于4GB的机器来说,最好安装64位系统。

PAE又是什么?见底层附

再回到开头的问题,换个问法,问你不换epoll,依然用select能不能做到大并发?

select的FD_SETSIZE默认1024/2048Linux是1024)。

方法就是重新设置FD_SETSIZE(FD集的大小)!重新编译内核!

那这样是不是就能满足IM服务器的最大连接数需求了?确实,数量是不是问题了,问题是性能了,因为遍历方式没变——仍然是遍历所有连接数,FD_SIZE的改变也意味着遍历时间的增长,类似于CPU有太多时间片轮转的后果,每一个都要等很久,拖累性能。

至于poll的最大连接数限制,是多少?

一个BUG

使用的开源库中作者使用了非阻塞connect使用select() 来等待超时,但是并未检查FD_SETSIZE,当文件描述符数目大于这个数目之后就会出现内存越界错误,造成coredump。

 

三、共享内存

这点实际上涉及到epoll的具体实现了。内核/用户空间 内存拷贝问题,如何让内核FD消息通知给用户空间呢?

在这个问题上select采取了内存拷贝方法。Poll也是么?应该是,poll和select基本无区别?(肯定多少还有点区别,只是这些缺点是相同的)

既然是内存拷贝,因为也要拷贝啊,还是慢!

对于poll来说需要将用户传入的 pollfd 数组拷贝到内核空间,因为拷贝操作和数组长度相关,时间上这是一个O(n)操作,当事件发生,poll返回将获得的数据传送到用户空间并执行释放内存和剥离等待队列等善后工作,向用户空间拷贝数据与剥离等待队列等操作的的时间复杂度同样是O(n)。


而epoll是共享内存,拷贝都不用,相对来说应该会更快。epoll是通过内核与用户空间mmap同一块内存实现的。 

mmap是什么

mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制,相比较在用户空间和内核空间互相拷贝数据,效率更高。在要求高性能的应用中比较常用。mmap映射内存必须是页面大小的整数倍,面向流的设备不能进行mmap,mmap的实现和硬件有关。

(涉及到内核和用户空间的概念,共享内存有没有安全隐患?)

四、触发方式也算一个

Epoll除了水平触发Level Trigger,还有个边缘触发Edge Trigger。按电气层面就是高低电平的区分和高低变化的边缘?

水平触发和边缘处罚的含义?不是电信号层面的含义!是用在epoll这个层面什么含义?那天那个人好像“背”过。

epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

什么意思?



另外还有,就是并发数,比如六万、十万,怎么测的

难道就是做循环,一大堆链接,加压力?


附:socket的FD与文件的FD的关联:

(可以理解为socketfd和文件的fd是一个数量限制,甚至他俩fd空间本来就是共用的?不能有命名冲突?)

想知道文件和socketfd是否共用空间,看看socket的跨进程共享也许有一定参考性,至少跨了!!!另外,应该可以编程测试,不过socketfd按文件的接口去操作不知道什么后果?话说!好像都是writeread操作fwritefread好像是特例。)

fd (file descriptor),这种一般是BSD Socket的用法,用在Unix/Linux系统上。在Unix/Linux系统下,一个socket句柄,可以看做是一个文件,在socket上收发数据,相当于对一个文件进行读写,所以一个socket句柄,通常也用表示文件句柄的fd来表示。(虽然说相当于文件,但是还没说完全等同)



附:PAE又是什么?

Physical Address Extend

物理地址扩展

“linux pae”一搜一堆的,有空可以去看,留意的话可以注意到某些内核都有“-pae”字样

pae支持方法:下载专门的pae内核包

http://mingyue19850801.blog.163.com/blog/static/19520820201312815458325/

怎么看我这个开了PAE

查看命令

我这台机器支持大内存,通过命令找PAE找到三个结果,应该是这三个文件都设置了。

 

 epoll特点总结 (https://mushiming.com/)  第2张

PAE的缺陷:

PAE能让32位系统去按64位寻址?总之是支持64GB内存,然后(有人说)不支持寻址?那还有什么用?

 

想想也是,以前服务器也要很大内存,而64位没那么普及,难道4G就是服务器内存极限?或者服务器确实很早普及64位?其实技术上也没什么难的,让32位去寻址64GB内存也就是64位寻址,只需要硬件有个小调整,就是那个地址寄存器吧(具体名词怎么叫都忘了)。应该也不对,是其他手段吧?因为只是软件设置啊!不然就是硬件已经兼容了这个功能,软件想打开就能打开,还是去搜PAE详细资料吧。

 

引用:

4g内存用32位都是加了中间层的,在ubuntu上叫ape内核,性能会损失。

 

THE END

发表回复