精华内容
下载资源
问答
  • 1、基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合: ...与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创
  • 多路复用技术

    千次阅读 2019-10-04 07:26:18
    多路复用技术 多路复用技术是把多个低速信道组合成一个高速信道的技术,它可以有效的提高数据链路的利用率,从而使得一条高速的主干链路同时为多条低速的接入链路提供服务,也就是使得网络干线可以同时运载大量的...

    多路复用技术

    多路复用技术是把多个低速信道组合成一个高速信道的技术,它可以有效的提高数据链路的利用率,从而使得一条高速的主干链路同时为多条低速的接入链路提供服务,也就是使得网络干线可以同时运载大量的语音和数据传输。多路复用技术是为了充分利用传输媒体,人们研究了在一条物理线路上建立多个通信信道的技术。

    多路复用技术的实质是,将一个区域的多个用户数据通过发送多路复用器进行汇集,然后将汇集后的数据通过一个物理线路进行传送,接收多路复用器再对数据进行分离,分发到多个用户。多路复用通常分为频分多路复用、时分多路复用、波分多路复用、码分多址和空分多址。

    频分多路复用

    频分多路复用技术FDM(Frequency Division MulTIplexing)。

    频分多路复用利用通信线路的可用带宽超过了给定的带宽这一优点。频分多路复用的基本原理是:如果每路信号以不同的载波频率进行调制,而且各个载波频率是完全独立的,即各个信道所占用的频带不相互重叠,相邻信道之间用“警戒频带”隔离,那么每个信道就能独立地传输一路信号。

    频分多路复用的主要特点是,信号被划分成若干通道(频道,波段),每个通道互不重叠,独立进行数据传递。每个载波信号形成一个不重叠、相互隔离(不连续)的频带。接收端通过带通滤波器来分离信号。频分多路复用在无线电广播和电视领域中的应用较多。ADSL也是一个典型的频分多路复用。ADSL用频分多路复用的方法,在PSTN使用双绞线上划分出三个频段:0~4kHz用来传送传统的语音信号;20~50kHz用来传送计算机上载的数据信息;150~500kHz或140~1100kHz用来传送从服务器上下载的数据信息。

    时分多路复用

    时分多路复用技术TDM(TIme Division MulTIplexing)

    时分多路复用是以信道传输时间作为分割对象,通过为多个信道分配互不重叠的时间片段的方法来实现多路复用。时分多路复用将用于传输的时间划分为若干个时间片段,每个用户分得一个时间片。时分多路复用通信,是各路信号在同一信道上占有不同时间片进行通信。由抽样理论可知,抽样的一个重要作用,是将时间上连续的信号变成时间上的离散信号,其在信道上占用时间的有限性,为多路信号沿同一信道传输提供条件。具体说就是把时间分成一些均匀的时间片,通过同步(固定分配)或统计(动态分配)的方式,将各路信号的传输时间配分在不同的时间片,以达到互相分开,互不干扰的目的。

    至2011年9月,应用最广泛的时分多路复用是贝尔系统的T1载波。T1载波是将24路音频信道复用在一条通信线路上,每路音频信号在送到多路复用器之前,要通过一个脉冲编码调制编码器,编码器每秒抽样8000次。24路信号的每一路,轮流将一个字节插入到帧中,每个字节的长度为8位,其中7位是数据位,1位用于信道控制。每帧由24&TImes;8=192位组成,附加1bit作为帧的开始标志位,所以每帧共有193bit。由于发送一帧需要125ms,一秒钟可以发送8000帧。因此T1载波数据传输速率为:

    193bit×8000=1544000bps=1544Kbps=1.544Mbps

    多路复用技术原理解析

    波分多路复用

    波分多路复用技术WDM(Wavelength Division Multiplexing)

    波分复用用同一根光纤内传输多路不用波长的光信号,以提高单根光纤的传输能力。因为光通信的光源在光通信的“窗口”上只占用了很窄的一部分,还有很大的范围没有利用。

    也可以这样认为WDM是FDM应用于光纤信道的一个变例。如果让不用波长的光信号在同一根光纤上传输而互不干扰,利用多个波长适当错开的光源同时在一根光纤上传送各自携带的信息,就可以增加所传输的信息容量。由于是用不同的波长传送各自的信息,因此即使在同一根光纤上也不会相互干扰。在接收端转换成电信号时,可以独立地保持每个不同波长的光源所传送的信息。这种方式就叫做“波分复用”。

    如果将一系列载有信息的不同波长的光载波,在光领域内以1至几百纳米的波长间隔合在一起沿单根光纤传输,在接收器再一一定的方法,将各个不同波长的光载波分开。在光纤上的工作窗口上安排100个波长不同的光源,同时在一根光纤上传送各自携带的信息,就能使光纤通信系统的容量提高100倍。

    码分多址

    码分多址技术CDMA(Code Division Multiple Access)

    码分多址是采用地址码和时间、频率共同区分信道的方式。CDMA的特征是个每个用户有特定的地址码,而地址码之间相互具有正交性,因此各用户信息的发射信号在频率、时间和空间上都可能重叠,从而使用有限的频率资源得到利用。

    CDMA是在扩频技术上发展起来的无线通信技术,即将需要传送的具有一定信号带宽的信息数据,从一个带宽远大于信号带宽的高速伪随机码进行调制,使原数据信号的带宽被扩展,再经载波调制并发送出去。接收端也使用完全相同的伪随机码,对接受的带宽信号作相关处理,把宽带信号换成原信息数据的窄带信号即解扩,以实现信息通信。

    不同的移动台(或手机)可以使用同一个频率,但是每个移动台(或手机)都被分配带有一个独特的“码序列”,该序列码与所有别的“序列码”都不相同,因为是靠不同的“码序列”来区分不同的移动台(或手机),所以各个用户相互之间也没有干扰从而达到了多路复用的目的。

    空分多址

    空分多址技术SDMA(Space Division Multiple Access)

    这种技术是将空间分割构成不同的信道,从而实现频率的重复使用,达到信道增容的目的。举例来说,在一个卫星上使用多个天线,各个天线的波束射向地球表面的不同区域地面上不同区域的地球站,他们在同一时间,即使用相同的频率进行工作,它们之间也不会形成干扰。SDMA系统的处理程序如下:

    1、系统将首先对来自所有天线中的信号进行快照或取样,然后将其转换成数字形式,并存储在内存中。

    2、计算机中的SDMA处理器将立即分析样本,对无线环境进行评估,确认用户、干扰源及所在的位置。

    3、处理器对天线信号的组合方式进行计算,力争最佳地恢复用户的信号。借助这种策略,每位用户的信号接收质量将提高,而其他用户的信号或干扰信号则会遭到屏蔽。

    4、系统进行模拟计算,使天线阵列可以有选择地向空间发送信号。再次在此基础上,每位用户的信号都可以通过单独的通信信道空间-空间信道实现高效的传输。

    5、在上述处理的基础上,系统就能够在每条空间信道上发送和接受信号,从而使这些信号称为双向信道。

    利用上述流程,SDMA系统就能够在一条普通信道上创建大量的频分、时分或码分双向空间信道,没一条信道扣可以完全活的整个阵列的增益和抗干扰功能。从理论上而言,带m个单元的阵列能够在每条普通行道上支持m条空间信道。但在实际应用中支持的信道数量将略低于这个数目,具体情况则取决于环境。由此可见,SDMA系统可使系统容量成倍增加,使得系统在有限的频谱内可以支持更多的用户,从而成倍的提高频谱使用效率。

    自2011年9月,近几十年来,无线通信经历了从模拟到数字,从固定到移动的重大变革。而就移动通信而言,为了更有效地利用有限的无线频率资源,时分多址技术(TDMA)、频分多址技术(FDMA)、码分多址技术(CDMA)得到了广泛的应用,并在此基础上建立了GSM和CDMA(是区别于3G的窄带CDMA)两大主要的移动通信网络。就技术而言,现有的这三种多址技术已经得到了充分的应用,频谱的使用效率已经发挥到了极限。空分多址技术(SDMA)则突破了传统的三维思维模式,在传统的三维技术的基础上,在第四维空间上极大地拓宽了频谱的使用方式,使用移动用户仅仅由于空间位置的不同而复用同一个传统的物理信道称为可能,并将移动通信技术引入了一个更为崭新的领域。

    多路复用技术原理解析

    多路复用是什么意思?

    在I/O编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术进行处理。I/O多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降底了系统的维护工作量,节省了系统资源,I/O多路复用的主要应用场景如下:

    服务器需要同时处理多个处于监听状态或者多个连接状态的套接字。

    服务器需要同时处理多种网络协议的套接字。

    目前支持I/O多路复用的系统调用有 select,pselect,poll,epoll,在Linux网络编程过程中,很长一段时间都使用select做轮询和网络事件通知,然而select的一些固有缺陷导致了它的应用受到了很大的限制,最终Linux不得不在新的内核版本中寻找select的替代方案,最终选择了epoll。epoll与select的原理比较类似,为了克服select的缺点,epoll作了很多重大改进,现总结如下:

    1. 支持一个进程打开的socket描述符(FD)不受限制(仅受限于操作系统的最大文件句柄数)。

    select最大的缺陷就是单个进程所打开的FD是有一定限制的,它由FD_SETSIZE设置,默认值是1024。对于那些需要支持上万个TCP连接的大型服务器来说显然太少了。可以选择修改这个宏,然后重新编译内核,不过这会带来网络效率的下降。我们也可以通过选择多进程的方案(传统的Apache方案)解决这个问题,不过虽然在Linux上创建进程的代价比较小,但仍旧是不可忽视的,另外,进程间的数据交换非常麻烦,对于Java由于没有共享内存,需要通过Socket通信或者其他方式进行数据同步,这带来了额外的性能损耗,增加了程序复杂度,所以也不是一种完美的解决方案。值得庆幸的是,epoll并没有这个限制,它所支持的FD上限是操作系统的最大文件句柄数,这个数字远远大于1024。例如,在1GB内存的机器上大约是10万个句柄左右,具体的值可以通过cat/proc/sys/fs/filemax察看,通常情况下这个值跟系统的内存关系比较大。

    2. I/O效率不会随着FD数目的增加而线性下降。

    传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,由于网络延时或者链路空闲,任一时刻只有少部分的socket是“活跃”的,但是select/poll每次调用都会线性扫描全部集合,导致效率呈现线性下降。epoll不存在这个问题,它只会对“活跃”的socket进行操作-这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的,那么,只有“活跃”的socket才会主动的去调用callback函数,其他idle状态socket则不会。在这点上,epoll实现了一个伪AIO。针对epoll和select性能对比的benchmark测试表明:如果所有的socket都处于活跃态。例如一个高速LAN环境,epoll并不比select/poll效率高太多;相反,如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。

    3. 使用mmap加速内核与用户空间的消息传递

    无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存复制就显得非常重要,epoll是通过内核和用户空间mmap使用同一块内存实现。

    4. epoll的API更加简单

    用来克服select/poll缺点的方法不只有epoll,epoll只是一种Linux的实现方案。在freeBSD下有kqueue,而dev/poll是最古老的Solaris的方案,使用难度依次递增。但epoll更加简单。

    转载于:https://www.cnblogs.com/wdp1990/p/11616190.html

    展开全文
  • IO多路复用技术 讲解 epoll 技术前,我们先了解一下什么是 IO 多路复用技术。 假设现在有一个服务器程序调用 accept 函数成功与客户端建立了连接,那么通过 accept 函数返回的通讯套接字,服务器就可以调用 ...

    IO多路复用技术

            讲解 epoll 技术前,我们先了解一下什么是 IO 多路复用技术。

            假设现在有一个服务器程序调用 accept 函数成功与客户端建立了连接,那么通过 accept 函数返回的通讯套接字,服务器就可以调用 write 往客户端写数据,也可以调用 read 读取从客户端发送过来的数据,这种单个线程去监听单个 IO 的读写情况我们就称为单路 IO 技术

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    
    #define SERVER_PORT 8080
    
    int main()
    {
        int listen_fd = socket(AF_INET,SOCK_STREAM,0);
        int conn_fd = 0;
        char data[] = "Hello World!";
    
        struct sockaddr_in server_addr;
        memset(&server_addr,0,sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        server_addr.sin_port = htons(SERVER_PORT);
          
        bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(server_addr));
        listen(listen_fd,32);
          
        while(1)
        {
            conn_fd = accept(listen_fd,(struct sockaddr *)NULL,NULL);
            write(conn_fd,data,strlen(data));
            close(conn_fd);
        }
        close(listen_fd);
        return 0;
    }

            那么什么是 IO 多路复用技术呢?假设我们现在的主线程同时监听着多个 IO(可以理解为同时监听着很多个通讯套接字),当某个通讯套接字发来数据的时候,操作系统告诉我们哪个通讯套接字有数据发送过来,当可以往某个通讯套接字发送数据时,操作系统告诉我们哪个通讯套接字可以写数据。这种可以监视多个 IO 描述符的读写就绪情况,并且这些 IO 操作都可以在一个线程内并发执行就叫做多路 IO 复用,这里的复用是指复用同一个线程。

     

    epoll 简介        

            了解了 IO 多路复用技术后,我们就来讲一下什么是 epoll。epoll 是一种典型的 IO 多路复用技术,epoll 最大的特点是支持高并发。传统 IO 多路复用技术 select、poll 由于操作系统的一些限制,在并发量上千级别的时候性能就会明显下降。

            epoll 和 kqueue(freebsd)都是支持高并发的 IO 多路复用技术。epoll 是 Linux 内核 2.6 版本才引入的,更早的内核版本是不支持 epoll 技术的。使用 epoll 技术,单独一台机器能支持少则数万多则数十万百万并发连接。高并发总是伴随着一定的系统资源消耗,比如需要内存去保存这个连接,因此并发量也总是有限的。

             假如现在 epoll 有十万个连接,同一时刻有几十个客户端发送数据,epoll 只会检查这几十个客户端发送的数据,如果使用 poll 或者 select,它们会检查所有的连接是否有发送数据,就是挨个连接询问是否有发数据过来,相比之下 epoll 的性能优势显而易见。

            很多服务器使用多进程或者多线程去支持高并发,但是创建进程或者线程切换都是比较消耗资源的,epoll 采用事件驱动机制,在单独的进程/线程中运行去收集、处理事件,没有创建进程或者线程切换的开销,因此更加高效。

    展开全文
  • Redis IO多路复用技术及epoll实现原理

    千次阅读 2019-09-17 22:09:27
    10、Redis IO多路复用技术以及epoll实现原理 Redis是一个单线程的但性能是非常好的内存数据库,主要用来作为缓存系统。Redis采用网络IO多路复用技术来保证在多连接的时候,系统吞吐量高。 10.1 为什么Redis要使用...

    10、Redis IO多路复用技术以及epoll实现原理

           Redis是一个单线程的但性能是非常好的内存数据库,主要用来作为缓存系统。Redis采用网络IO多路复用技术来保证在多连接的时候,系统吞吐量高。

    10.1 为什么Redis要使用IO多路复用

           首先,Redis是跑在单线程中的,所有的操作都是顺序线性执行的,但是由于读写操作等待用户输入或者输出都是阻塞的,所以I/O操作往往不能直接返回,这会导致某一文件的I/O阻塞导致整个进程无法为客户服务,而I/O多路复用模型就是为了解决这个问题而出现的。

     

           select、poll、epoll都是IO多路复用的模型。I/O多路复用就是通过一种机制,可以监视多个文件描述符,一旦某个描述符就绪,能够通知应用程序进行相应操作。

           Redis的I/O模型使用的就是epoll,不过它也提供了select和kqueue的实现,默认采用epoll。

           那么epoll到底什么东西?我们一起来看看。

     

    10.2 epoll实现机制

    10.2.1 场景举例

           设想一个如下场景:

           有100W个客户端同时与一个服务器保持着TCP连接。而每一时刻只有几百上千个TCP连接是活跃着的(事实上大部分场景都是这样的情况)。如何实现这样的高并发?

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

           如果没有I/O事件发生,我们的程序就会阻塞在select处。但是依然存在一个问题,我们从select那里仅仅知道了有I/O事件发生,但却并不知道是哪几个流(可能一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出或者写入数据的流,对它们进行操作。

           但是,使用select,我们有O(n)无差别轮询复杂度,同时处理的流越多,每一次无差别的轮询时间就越长。

     

    10.2.2 select/poll缺点

           总结:select/poll缺点如下:

    1. 每次调用select/poll都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大;
    2. 同时每次调用select/poll都需要在内核遍历传进来的所有fd,这个开销在fd很多时会很大;
    3. select支持的文件描述符数量太小,默认1024;
    4. select返回的是含有整个句柄的数组,应用程序需要遍历整个数组才能发现哪些句柄发生了事件;
    5. select的触发方式是水平触发,应用程序如果没有完成对一个已经就绪的文件描述符进行IO操作,那么之后每次select调用还是会将这些文件描述符通知给进程;

     

            相比于select模型,poll模型使用链表保存文件描述符,因此没有了监视文件数量的限制,但是其他缺点依然存在。

     

    10.2.3 epoll实现机制

           epoll的设计和实现与select完全不同。epoll是poll的一种优化,返回后不需要对所有的fd进行遍历,它在内核中维护了fd列表。select和poll是将这个内核列表维持在用户态,然后复制到内核态。与select/poll不同,epoll不在是一个单独的调度系统,而是由epoll_create / epolll_ctl / epoll_wait三个系统组成,后面将会看到这样做的好处。epoll在2.6以后的内核才支持。

           epoll通过在Linux内核中申请一个简易的文件系统(文件系统一般用什么数据结构?B+树)。把原先的select/poll调用分成三个部分。

    1. 调用epoll_create()建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源);
    2. 调用epoll_ctl向epoll对象中添加这100W个连接的套接字;
    3. 调用epoll_wait收集在这上面发生的事件连接。

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

     

    10.2.4 epoll优点

    1)epoll没有最大并发连接限制,上限是最大可以打开的文件的数目,这个数字远大于“2048”,**一般来说,这个数目跟系统内存关系很大**,具体数目可以cat /proc/sys/fs/file-max查看。

     

    2)效率提升,epoll最大的优点就在于它只管你活跃的连接,而跟连接总数无关,因此在实际的网络环境中,epoll的效率会远远高于select/poll。

     

    3)无内存拷贝,epoll在这点上使用了“共享内存”,这个内存拷贝也就省略了。

     

    10.3 Redis epoll底层实现

            当某一进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体,这个结构体中有两个成员与epoll的使用方式密切相关。

    eventpoll结构体如下所示:
    	struct eventpoll{
    
    	……
    	/* 红黑树根节点,这棵树中存储着所有添加到epoll中需要监控的事件 */
    	struct rb_root rbr;
    
    	/* 双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件 */
    	struct list_head rdlist;
    	……
    
    };
    

            每一个epoll对象都有一个独立的eventpoll结构体,用于存放通过epoll_ctl方法向epoll对象中添加进来的事件。这些事件都会挂在红黑树中,如此,重复添加的事件就可以通过红黑树高效标识出来(红黑树插入事件效率是lgn,其中n为树的高度)。

     

            而所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当相应的事件发生时,会调用这个回调方法。这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双向链表中。

    在epoll中,每个事件都会建立一个epitem结构体,如下所示:
    struct epitem{
    	// 红黑树节点
    	struct rb_node rbn;
    
    	// 双向链表节点
    	struct list_head rdlist;
    
    	// 事件句柄信息
    	struct epoll_filefd ffd;
    
    	// 指向其所属的eventpoll对象
    	struct eventpoll *ep;
    
    	// 期待发生的事件类型
    	struct epoll_event event;
    
    }
    

            当调用epoll_wait方法检查是否有事件发生时,只需要检查eventpoll对象中的rdlist双向链表中是否有epitem元素即可。如果rdlist不为空,则把发生的事件复制到用户态,同时将事件的数量返回给用户。

    优势:

    1. 不用重复传递。我们调用epoll_wait时候就相当于以前调用select/poll,但这时却不用传递socket文件句柄给内核,因为内核已经在epoll_ctl中拿到了要监控的文件句柄列表。
    2. 在内核里,一切皆文件。所以,epoll向内核注册了一个文件系统,用于存储上述被监控socket。当你调用epoll_create时,就会在这个虚拟的epoll文件系统中创建一个file结点。当然这个file不是普通的文件,它只服务于epoll。
    3. 极其高效的原因。这是由于我们在调用epoll_create时候,内核除了帮我们在epoll文件系统中创建了file结点,在内核cache里创建了个红黑树用于储存以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时候,仅仅观察这个list链表有没有数据即可。如果有数据就立即返回,没有数据就sleep,等到timeout时候,即使list没有数据也返回。所以epoll_wait非常高效。 

            epoll在被内核初始化时(操作系统启动),同时会开辟出epoll自己的内核高速cache区,用于安置我们每一个想要监控的socket,这些socket会以红黑树的形式保存在内核cache里,以支持快速的查找、插入、删除。这个内核高速cache区,就是建立连续的物理内存页,然后在此之上建立slab层,简单的说,就是物理上分配好你想要的size内存对象,每次使用都是使用空闲的已经分配好的对象。

     

    这个准备就绪的list链表是怎么维护的呢?

            当我们执行epoll_ctl时,除了把socket放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪的list链表里。所以,当一个socket上有数据到了,内核再把网卡中的数据copy到内核中后,就把socket插入到准备就绪的链表里了。(备注:好好理解这句话)

            从上面可以看出,epoll基础就是回调。

            如此,一颗红黑树,一张准备就绪的句柄链表,少量的内核cache,就帮我们解决了高并发下的socket处理问题。

            执行epoll_create时,创建了红黑树和就绪链表,执行epoll_ctl时,如果增加socket句柄,则检查红黑树中是否存在,存在就立即返回,不存在则添加进红黑树,然后向内核注册回调函数,用于当中断事件来临时向准备就绪链表中插入数据。执行epoll_wait时,立刻返回准备就绪链表里的数据即可。

           最后看看epoll独有的两种模式LT和ET。无论是LE还是ET都适用于以上所说的流程。区别是,LT模式下,只要一个句柄上的事件一次没有处理完,会在以后调用epoll_wait时此次返回这个句柄,而ET模式仅在第一次返回。

           关于LT和ET,有一段描述,LT和ET都是电子里面的术语,ET是边缘触发,LT是水平触发,一个表示只有在变化的边际触发,一个表示在某个阶段都会触发。

           LT,ET这件事怎么做到的呢?当一个socket句柄上有事件时,内核会把该句柄插入上面所说的准备就绪的list链表,最后,epoll_wait干了这件事情,就是检查这些socket,如果不是ET模式(就是LT模式的句柄了),并且这些socket上确实有未处理的事件时,又把该句柄放回刚刚清空的准备就绪链表了。所以,非ET的句柄,只要它上面还有事件,epoll_wait每次都会返回这个句柄。(从上面这段,可以看出,LT还有一个回放过程,低效了。)

     

    觉着老铁我写的还不错滴请继续关注下一章:终章篇咯!

     

    展开全文
  • 一文读懂I/O多路复用技术

    万次阅读 多人点赞 2017-11-21 12:54:24
    针对这种困境的一个解决办法就是I/O多路复用技术。基本思路就是使用select函数,要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序。--《UNIX网络编程》 我们以书中的这段描述来引出我们要...

    前言

    当我们要编写一个echo服务器程序的时候,需要对用户从标准输入键入的交互命令做出响应。在这种情况下,服务器必须响应两个相互独立的I/O事件:1)网络客户端发起网络连接请求,2)用户在键盘上键入命令行。我们先等待哪个事件呢?没有哪个选择是理想的。如果在acceptor中等待一个连接请求,我们就不能响应输入的命令。类似地,如果在read中等待一个输入命令,我们就不能响应任何连接请求。针对这种困境的一个解决办法就是I/O多路复用技术。基本思路就是使用select函数,要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序。--《UNIX网络编程》
    我们以书中的这段描述来引出我们要讲述的I/O多路复用技术。

    I/O多路复用概述

     


    I/O多路复用,I/O就是指的我们网络I/O,多路指多个TCP连接(或多个Channel),复用指复用一个或少量线程。串起来理解就是很多个网络I/O复用一个或少量的线程来处理这些连接。现在大部分讲述I/O多路复用的文章用到的上面这张图是《UNIX网络编程》一书的。那么这也是当前我们理解I/O多路复用技术的基础知识。从这张图里面我们GET到哪些点呢?
    个人理解有:
    1、怎么区分的应用进程与内核
    2、有两次系统调用分别是select和recvfrom
    3、两次系统调用进程都阻塞
    4、等待哪些数据准备好
    下面我们逐一阐述。

     

    二、用户进程和内核

     

    根据网络OSI七层模型和网际网协议族的同比,我们可以知道这里说的用户进程和内核是以传输层为分割线,传输层以上(不包括)是指用户进程,传输层以下(包括)是指内核。上三层,web客户端比如浏览器、web服务器这些都属于应用层,里面跑的程序则是应用进程。下四层处理所有的通信细节,发送数据,等待确认,给无序到达的数据排序等等。这四层也是通常作为操作系统内核的一部分提供。由此可见图1中说的系统调用的地方正是第四层和第五层之间的位置。

     

    为了理解用户进程和内核,再来看一张图,网络数据流向图。也清晰的标明了用户进程和内核的位置。值得注意的一点是客户与服务器之间的信息流在其中一端是向下通过协议栈的,跨越网络后,在另一端是向上通过协议栈的。这张图描述的是局域网内,如果是在广域网那么就是通过很多个路由器承载实际数据流。

     

    三、select和recvfrom

    3.1、select

    理解了select就抓住了I/O多路复用的精髓,对应的操作系统中调用的则是系统的select函数,该函数会等待多个I/O事件(比如读就绪,写)的任何一个发生,并且只要有一个网络事件发生,select线程就会执行。如果没有任何一个事件发生则阻塞。我们在下面小节中会重点讲述。函数如下:

    #include<sys/select.h>
    #include<sys/time.h>
    int select(int maxfdpl,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout);
    

    从这个函数的定义中的参数,我们能够看出它描述的是,当调用select的时候告知内核对那些事件(读就绪,写)感兴趣以及等待多长时间。

    为了方便我们理解select调用,可以参照下面这张图,是jdk的基于I/O多路复用技术的NIO实现。重点在于理解Selector复用器。

     

    大致代码如下:

     

    ServerSocketChannel serverChannel = ServerSocketChannel.open();// 打开一个未绑定的serversocketchannel   
    Selector selector = Selector.open();// 创建一个Selector
    serverChannel .configureBlocking(false);//设置非阻塞模式
    serverChannel .register(selector, SelectionKey.OP_READ);//将ServerSocketChannel注册到Selector
    
    
    while(true) {
      int readyChannels = selector.select();
      if(readyChannels == 0) continue;
      Set selectedKeys = selector.selectedKeys();
      Iterator keyIterator = selectedKeys.iterator();
      while(keyIterator.hasNext()) {
        SelectionKey key = keyIterator.next();
        if(key.isAcceptable()) {
            // a connection was accepted by a ServerSocketChannel.
        } else if (key.isConnectable()) {//连接就绪
            // a connection was established with a remote server.
        } else if (key.isReadable()) {//读就绪
            // a channel is ready for reading
        } else if (key.isWritable()) {//写就绪
            // a channel is ready for writing
        }
        keyIterator.remove();
      }
    }
    

    3.2、recvfrom

    recvfrom一般用于UDP协议中,但是如果在TCP中connect函数调用后也可以用。用于从(已连接)套接口上接收数据,并捕获数据发送源的地址。也就是我们本文中以及书中说的真正的I/O操作。

    四、阻塞、非阻塞

     

    这张图可以看出阻塞式I/O、非阻塞式I/O、I/O复用、信号驱动式I/O他们的第二阶段都相同,也就是都会阻塞到recvfrom调用上面就是图中“发起”的动作。异步式I/O两个阶段都要处理。这里我们重点对比阻塞式I/O(也就是我们常说的传统的BIO)和I/O复用之间的区别。

     

    阻塞式I/O和I/O复用,两个阶段都阻塞,那区别在哪里呢?就在于第三节讲述的Selector,虽然第一阶段都是阻塞,但是阻塞式I/O如果要接收更多的连接,就必须创建更多的线程。I/O复用模式下在第一个阶段大量的连接统统都可以过来直接注册到Selector复用器上面,同时只要单个或者少量的线程来循环处理这些连接事件就可以了,一旦达到“就绪”的条件,就可以立即执行真正的I/O操作。这就是I/O复用与传统的阻塞式I/O最大的不同。也正是I/O复用的精髓所在。

    从应用进程的角度去理解始终是阻塞的,等待数据和将数据复制到用户进程这两个阶段都是阻塞的。这一点我们从应用程序是可以清楚的得知,比如我们调用一个以I/O复用为基础的NIO应用服务。调用端是一直阻塞等待返回结果的。
    从内核的角度等待Selector上面的网络事件就绪,是阻塞的,如果没有任何一个网络事件就绪则一直等待直到有一个或者多个网络事件就绪。但是从内核的角度考虑,有一点是不阻塞的,就是复制数据,因为内核不用等待,当有就绪条件满足的时候,它直接复制,其余时间在处理别的就绪的条件。这也是大家一直说的非阻塞I/O。实际上是就是指的这个地方的非阻塞。

    当我们阅读《UNIX网络编程》(第三版)一书的时候。P124,6.2.3小节中“而不是阻塞在真正的I/O系统调用上”这里的阻塞是相对内核来说的。P127,6.2.7小节“因为其中真正的I/O操作(recvfrom)将阻塞进程”这里的阻塞是相对用户进程来说的。明白了这两点,理解起来就不矛盾了,而且一通到底!

    五、适用场景

    当服务程序需要承载大量TCP链接的时候,比如我们的消息推送系统,IM通讯,web聊天等等,在我们已经理解Selector原理的情况下,知道使用I/O复用可以用少量的线程处理大量的链接。I/O多路复用技术以事件驱动编程为基础。它运行在单一进程上下文中,因此每个逻辑流都能访问该进程的全部地址空间,这样在流之间共享数据变得很容易。

    六、总结

    我们通常说的NIO大多数场景下都是基于I/O复用技术的NIO,比如jdk中的NIO,当然Tomcat8以后的NIO也是指的基于I/O复用的NIO。注意,使用NIO != 高性能,当连接数<1000,并发程度不高或者局域网环境下NIO并没有显著的性能优势。如果放到线上环境,网络情况在有时候并不稳定的情况下,这种基于I/O复用技术的NIO的优势就是传统BIO不可同比的了。那么使用select的优势在于我们可以等到网络事件就绪,那么用少量的线程去轮询Selector上面注册的事件,不就绪的不处理,就绪的拿出来立即执行真正的I/O操作。这个使得我们就可以用极少量的线程去HOLD住大量的连接。

    转载请注明作者及出处,并附上链接https://blog.csdn.net/wangxindong11/article/details/78591308

    参考资料:
    《UNIX网络编程》、《深入理解计算机操作系统》

    文章同步更新到公众号

     

    展开全文
  • Java IO多路复用技术详解

    万次阅读 2017-04-28 09:49:58
    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型。 (2)同步非阻塞IO(Non-blocking IO):默认创建的...(3)IO多路复用(IO Multiplexi
  • Netty系列---IO多路复用技术

    千次阅读 2019-10-24 19:41:46
    形成的原因: 如果一个I/O流进来,我们就开启一个进程处理这个I/O流。...所以人们提出了I/O多路复用这个模型,一个线程,通过记录I/O流的状态来同时管理多个I/O,可以提高服务器的吞吐能力。 ...
  • 日前,德州仪器(TI)宣布推出三款高速视频多路复用器OPA875、OPA3875与OPA4872,这些器件结合了高带宽、高压摆率、快速开关时间以及低开关干扰等多种优势,能够显著优化专业视频应用的性能。这种高速多路复用器可以在...
  • I/O多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的...
  • 为什么Redis快呢,其实在学习完了应用场景和集群等模式后可以回归本源了,用Redis的本质原因到底是什么?Redis的设计方式有什么好处,这是向更...redis是单线程的,省去了很上下文切换线程的时间,单线 避免了线程切
  • 多路复用的好处

    2020-10-28 21:17:38
    I/O多路复用可以通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。它的最大优势是系统开销小,并且不需要创建新的进程或者线程,降低了系统的资源开销 ...
  • Redis之I/O多路复用技术(multiplexing)

    万次阅读 2020-06-25 21:43:37
    在面试中通常会有这样子的场景 ↓↓↓↓↓↓ 面试官:看你的简历写到项目中有用到redis,可以聊聊...面试官:那你了解I/O多路复用技术在redis中的应用吗 求职者:不是很了解。。。 在了解I/O多路复用之前,我们可.
  • Redis IO多路复用技术以及epoll实现原理

    万次阅读 多人点赞 2018-05-10 21:54:39
    redis 采用网络IO多路复用技术来保证在多连接的时候, 系统的高吞吐量。为什么 Redis 中要使用 I/O 多路复用这种技术呢?首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待...
  • I/O多路复用技术 在I/O编程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术进行处理。I/O多路复用技术通过把多个I/O阻塞复用到同一个select阻塞上,从而实现系统在单线程的情况下可以...
  • IO多路复用技术

    2019-10-18 11:06:04
    与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。 IO多路复用(I/O multiplexing )的设计理念: multiplexing ...
  • 什么是IO多路复用,理解IO多路复用

    千次阅读 多人点赞 2020-04-03 12:18:00
    三、I/O多路复用 好了,我们讲了这么多,再来总结一下,到底什么是I/O多路复用。 先讲一下I/O模型: 首先,输入操作一般包含两个步骤: 等待数据准备好(waiting for data to be ready)。对于一个套接口上的操作,...
  • 多路复用中,用户上固定接入的,或是半固定接入的,而多址接入时网络资源是动态分配的。 频分复用FDM: 一般采用单边带调制技术。——数字和模拟通信均可使用。 12路频分复用电话系统称为一个基群,5个基群组成一个...
  • I/O多路复用技术

    2018-12-17 23:03:35
    在I/O编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术自来。 它通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单纯种的情况下可以同时处理多个客户端请求。 ...
  • TCP/IP多路复用

    千次阅读 2021-02-28 17:08:43
    所有网络通信的本质目标就是...因此这里需要用到一个叫作多路复用(Multiplex)的技术多路复用,就是多个信号,复用一个信道。 传输层多路复用 多个请求复用一个 TCP 连接。 多个请求相当于并行的发送请求。即使其
  • 解读I/O多路复用技术

    2021-01-04 22:51:02
    前言 当我们要编写一个echo服务器程序的时候,需要对用户从标准输入键入的交互命令做出响应。...针对这种困境的一个解决办法就是I/O多路复用技术。基本思路就是使用select函数,要求内核挂起进程,只有在一个或多个I/
  • 多路复用I/O的优缺点

    千次阅读 2017-09-14 16:29:43
    多路复用I/O的优缺点 多路复用I/O技术由操作系统提供支持,并提供给各种高级语言进行使用。它针对阻塞式同步I/O和非阻塞式同步I/O而言有很多优势,最直接的效果就是它绕过了I/O在操作系统层面的accept()方法的阻塞...
  • IO多路复用

    千次阅读 2019-06-23 14:48:40
    IO多路复用 同步IO、异步IO、IO多路复用 IO两个阶段 IO过程分两阶段: 数据准备阶段。从设备读取数据到内核空间的缓冲区 内核空间复制回用户空间进程缓冲区阶段 发生IO的时候: 内核从IO设备读数据(例如:淘米...
  • 通俗易懂说多路复用(1)select1. 什么是多路复用?定义通俗易懂的举例种类2. 什么是select?背景定义3. 参考: 1. 什么是多路复用? 定义 多路复用就是通过一种机制,可以监听多个描述符,一旦某个描述符就绪(可以...
  • 一、I/O多路复用简介 高性能是每个程序员的追求,无论写一行代码还是做一个系统,都希望能够达到高性能的效果。高性能架构设计主要集中在两方面: 尽量提升单服务器的性能,将单服务器的性能发挥到极致 如果单...
  • Note5:多路复用

    2019-03-27 21:35:07
    1. 五种网络I/O模型 ...对于网络IO来说,很时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包),这个时候内核就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。当内核一直等...
  • 多路复用技术概述

    千次阅读 2018-07-29 18:51:36
    概述 频分复用(Frequency Division Multiplexing) 时分复用(Time Division Multiplexing) ...数据是在物理链路的信道中传输的,通常一条链路上会有条信道。在默认情况下,一条信道只传输一路信...
  • Redis I/O 多路复用

    万次阅读 多人点赞 2019-05-19 19:18:01
    为什么 Redis 中要使用 I/O 多路复用这种技术呢? 首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回...
  • I/O 多路复用技术

    2020-09-16 11:19:22
    在 I/O 编程过程中,当需要同时处理多个客户端请求时,可以利用多线程或 I/O 多路复用技术进行处理。本篇博客我就来简单介绍 I/O 多路复用相关知识。 什么是 I/O 多路复用技术 I/O 多路复用技术是指多个网络 I/O ...
  • IO多路复用适合用于:处理过程简单,进/线程池适合处理过程复杂 的情况 IO多路复用+单进(线)程比较省资源适合处理大量的闲置的IO IO多路复用+多单进(线)程与线程池方案相比有好处,但是并不会 有太大的优势如果...
  • I/O多路复用(multiplexing)的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作 select、poll 和 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,700
精华内容 15,080
关键字:

多路复用技术的优点