多路转接模型&多路复用模型

多路转接模型&多路复用模型

功能:

同时监控大量描述符,然后逐个针对就绪的描述符进行处理;

针对大量描述符进行IO事件监控,让进程可以只针对就绪的描述符进行IO操作,提高IO效率,避免针对未就绪的描述符操作而导致的效率降低或阻塞;

eg:

以前的TCP服务器会为每个客户端都创建一个新的套接字用于与指定客户端通信,由于不知道哪个描述符什么时候有数据到来,所以会先获取新建连接再获取数据

但是由于可能会在没有新建连接时调用accept,在指定客户端没有数据时调用recv,所以可能会导致程序阻塞

以前的解决方案为建立多执行流来负责多客户端的通信,这样会占用较多资源;

使用多路转接模型来进行IO事件的监控,可以让进程直到哪个描述符有数据到来,也就是针对已经就绪的描述符进行操作。

多路转接模型实现:

select&poll相较于epoll,尽管监控性能epoll更高,但是对于单个描述符的超时控制上更加简便;

多路转接模型主要适用于监控大量描述符,但是只有少量活跃的场景,如果活跃描述符比较多需要搭配线程池一起使用;

select模型:进行大量描述符事件监控

操作流程:

①针对不同的IO事件(可读事件,可写事件,异常事件),定义不同的描述符集合,把要监控的描述符添加到对应集合中;

②调用监控接口,将集合拷贝到内核中进行轮询遍历监控,当有描述符就绪或者监控超时都没有就绪则返回;

:监控调用前,会将集合中所有没有就绪的描述符从集合中移除掉(监控调用返回后,集合中只存在就绪的描述符)。

③调用返回后,集合中存在的描述符即就绪,可进而进行操作;

select模型优缺点:

优点:跨平台移植性好;

缺点:

①能够添加的描述符有上限限制,

select的监控集合是一个数组,当作位图使用,因此能监控多少描述符取决于有多少比特位;

②select监控多次进行轮询遍历集合,性能会随着描述符的增多而下降;

③select会修改集合,因此每次监控都需要重新添加买哦书夫到集合中;

④select返回的是一个就绪的描述符集合,并不会基于就绪的描述符,增加操作复杂度;

poll模型:针对大量描述符进行监控,但是会为每个描述符设置事件结构体

操作流程:

①定义要监控的描述符事件结构体数组,向数组中添加需要监控的描述符及时间信息;

②调用监控接口开始监控,将需要监控的数据拷贝到内核中进行监控(多次轮询遍历),监控调用返回前会将描述符实际就绪的事件填充到revents成员中,若没有就绪事件则置为0;

③监控调用接口调用完毕后,遍历事件结构体数组,通过每个元素的revents成员确定描述符就绪了什么事件进行操作;

poll模型优缺点:

优点:

①相较于select操作更加简单;

②所能监控的描述符数量没有上限;

缺点:

①无法跨平台(Linux);

②监控原理设计多次轮询遍历,描述符数量增加效率降低(比不上epoll);

epoll模型:针对大量描述符进行监控,不可跨平台,效率高于poll

操作流程:

①创建epoll句柄,内核中创建了一个结构体,里面有一颗红黑树以及一个双向链表;

②向epoll添加监控;

③开始监控,epoll是一个异步阻塞操作,epoll的监控实际上是告诉系统可以监控了,具体监控操作由系统完成 ;

系统在进行监控的时候为每个描述符都定义了一个回调函数,一旦描述符就绪了指定事件,则会由回调函数把描述符对应的事件结构体添加进rdllist双向链表

我们的进程只需要看rdllist双向链表是否为空就可以确定是否有描述符就绪;

epoll事件触发方式:

①水平触发(默认触发方式):

可读:只要发送缓冲区中有数据就会触发事件;

可写:只要发送缓冲区有剩余空间就会触发事件;

②边缘触发(EPOLLET):

可读:只有新数据到来才会触发事件,如果没有新数据来,不管发送缓冲区有没有数据都不会触发;

可写:发送缓冲区剩余空间从无到有才会触发事件;

边缘触发思想是为了让程序员一次性把请求处理完毕,减少处理次数,以此提高效率;

在边缘触发方式下需要将描述符设置为非阻塞,避免由于缓冲区没有数据后阻塞的发生(没有数据就会报错返回);

适用场景:

①想要尽量一次性处理所有请求,减少事件触发次数提高效率;

②避免水平触发模式下,因为半条数据没有进行处理而不断触发事件的情况;

int fcntl(int fd, int cmd, ...);
//设置非阻塞的接口

int flag = fcntl(fd, F_GETFL, 0);//获取描述符原本属性

fcntl(fd, F_SETFL, flag|O_NOBLOCK);//原有属性上新增非阻塞属性

epoll模型优缺点:

优点:

①所能监控的描述符数量没有上限

性能不会随着描述符的增大而下降,因为监控原理是异步操作,让系统进行监控,系统为事件做了回调函数将就绪事件添加至就绪链表,进程只需要对就绪链表是否为空进行判断即可确定有无描述符就绪,其中没有轮询遍历操作

直接返回就绪的事件信息,可以直接对就绪的描述符进行指定事件的操作,不需要空遍历判断哪个描述符就绪;

缺点:

跨平台移植性较差;

epoll的惊群问题:

多路转接模型应用场景:

①有大量描述符需要进行IO就绪事件的监控,但是同一时间只有少量活跃的场景(或者搭配多执行流进行处理);

②针对单个描述符有收发数据的超时控制的场景;

猜你喜欢

转载自blog.csdn.net/SFDWU3QVG/article/details/126818929