精华内容
下载资源
问答
  • 多路复用模型

    2012-09-10 17:15:19
    多路复用的方式是真正实用的服务器程序,非多路复用的网络程序只能作为学习或着陪测的角色。本文说下个人接触过的多路复用函数:select/poll/epoll/port。kqueue的*nix系统没接触过,估计熟悉了上面四种,kqueue也...

    http://blog.sina.com.cn/s/blog_4d8498800100af00.html

    多路复用的方式是真正实用的服务器程序,非多路复用的网络程序只能作为学习或着陪测的角色。本文说下个人接触过的多路复用函数:select/poll/epoll/port。kqueue的*nix系统没接触过,估计熟悉了上面四种,kqueue也只是需要熟悉一下而已。
    一、select模型
    select原型:

    int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

    其中参数n表示监控的所有fd中最大值+1。
    和select模型紧密结合的四个宏,含义不解释了:

    FD_CLR(int fd, fd_set *set);
    FD_ISSET(int 
    fd, fd_set *set);
    FD_SET(int 
    fd, fd_set *set);
    FD_ZERO(fd_set 
    *set);

    理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。
    (1)执行fd_set set;FD_ZERO(&set);则set用位表示是0000,0000。
    (2)若fd=5,执行FD_SET(fd,&set);后set变为0001,0000(第5位置为1)
    (3)若再加入fd=2,fd=1,则set变为0001,0011
    (4)执行select(6,&set,0,0,0)阻塞等待
    (5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。

    基于上面的讨论,可以轻松得出select模型的特点:
    (1)可监控的文件描述符个数取决与sizeof(fd_set)的值。我这边服务器上sizeof(fd_set)=512,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是512*8=4096。据说可调,另有说虽然可调,但调整上限受于编译内核时的变量值。本人对调整fd_set的大小不太感兴趣,参考http://www.cppblog.com/CppExplore/archive/2008/03/21/45061.html中的模型2(1)可以有效突破select可监控的文件描述符上限。
    (2)将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd,一是用于再select返回后,array作为源数据和fd_set进行FD_ISSET判断。二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数。
    (3)可见select模型必须在select前循环array(加fd,取maxfd),select返回后循环array(FD_ISSET判断是否有时间发生)。

    下面给一个伪码说明基本select模型的服务器模型:

    array[slect_len];
    nSock=0;
    array[nSock++]=listen_fd;(之前listen 
    port已绑定并listen)
    maxfd=listen_fd;
    while {
     
      FD_ZERO(&set);
     
      foreach (fd in array) 
     
       {
     
          fd大于maxfd,则maxfd=fd
     
          FD_SET(fd,&set)
     
      }
     
      res=select(maxfd+1,&set,0,0,0);
     
      if(FD_ISSET(listen_fd,&set))
     
       {
     
          newfd=accept(listen_fd);
     
          array[nsock++]=newfd;
     
               if(--res<=0)continue
     
      }
     
      foreach 下标1开始 (fd in array) 
     
       {
     
          if(FD_ISSET(fd,&set))
     
             执行读等相关操作
     
             如果错误或者关闭,则要删除该fd,将array中相应位置和最后一个元素互换就好,nsock减一
     
                if(--res<=0)continue

     
      }
    }

    二、poll模型
    poll原型:

    int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
    struct 
    pollfd {
     
                          int fd;           
     
                          short events    
     
                          short revents;    
     
                  };

    和select相比,两大改进:
    (1)不再有fd个数的上限限制,可以将参数ufds想象成栈低指针,nfds是栈中元素个数,该栈可以无限制增长
    (2)引入pollfd结构,将fd信息、需要监控的事件、返回的事件分开保存,则poll返回后不会丢失fd信息和需要监控的事件信息,也就省略了select模型中前面的循环操作,返回后的循环仍然不可避免。另每次poll阻塞操作都会自动把上次的revents清空。
    poll的服务器模型伪码:

    struct pollfd fds[POLL_LEN];
    unsigned 
    int nfds=0;
    fds[0].fd=server_sockfd;
    fds[0].events=POLLIN|POLLPRI;
    nfds++;
    while {
     
     res=poll(fds,nfds,-1);
     
     if(fds[0].revents&(POLLIN|POLLPRI)){执行accept并加入fds中,if(--res<=0)continue}
     
     循环之后的fds,if(fds[i].revents&(POLLIN|POLLERR )){操作略if(--res<=0)continue}
    }

    注意select和poll中res的检测,可有效减少循环的次数,这也是大量死连接存在时,select和poll性能下降厉害的原因。

    三、epoll模型

    epoll阻塞操作的原型:

    int epoll_wait(int epfd, struct epoll_event eventsint maxevents, int timeout)
    epoll引入了新的结构epoll_event。
    typedef 
    union epoll_data {
     
                    void *ptr;
     
                    int fd;
     
                    __uint32_t u32;
     
                    __uint64_t u64;
     
               epoll_data_t;

     
               struct epoll_event {
     
                    __uint32_t events 
     
                    epoll_data_t data;  
     
               };

    与以上模型的优点:
    (1)它保留了poll的两个相对与select的优点
    (2)epoll_wait的参数events作为出参,直接返回了有事件发生的fd,epoll_wait的返回值既是发生事件的个数,省略了poll中返回之后的循环操作。
    (3)不再象select、poll一样将标识符局限于fd,epoll中可以将标识符扩大为指针,大大增加了epoll模型下的灵活性。
    epoll的服务器模型伪码:

    epollfd=epoll_create(EPOLL_LEN);
    epoll_ctl(epollfd,EPOLL_CTL_ADD,server_sockfd,&ev)
    struct 
    epoll_event events[EPOLL_MAX_EVENT];
    while
    {
    nfds=epoll_wait(epollfd,events,EPOLL_MAX_EVENT,-1);
    循环nfds,是server_sockfd则accept,否则执行响应操作
    }

    epoll使用中的问题:
    (1)epoll_ctl的EPOLL_CTL_DEL操作中,最后一个参数是无意义的,但是在小版本号过低的2.6内核下要求最后一个参数一定非NULL,否则返回失败,并且返回的errno在manepoll_ctl中不存在,因此安全期间,保证epoll_ctl的最后一个参数总非NULLL。
    (2)如果一个fd(比如管道)的事件导致了另一个fd2的删除,则必须扫描返回结果集中是否有fd2,有则在结果集中删除,避免冲突。
    (3)有文章说epoll在G网环境下性能会低于poll/select,看有些测试,给出的拐点在2w/s并发之后,我本人的工作范围不可能达到这么高的并发,个人在测试性能的时候最大也是取的1w/s的并发,一个是因为系统单进程允许打开的文件描述符最大值,4w的数字太高了,另一个就是我这边服务器的性能达不到那么高的性能,极限1.7w/s的响应,那测试的数据竟然在2w并发的时候还有2w的响应,不知道是什么硬件配置。或许等有了G网的环境,会关注epoll高并发下的性能下降


    (4)epoll的LT和ET性能的差异,我测试的数据表明两者性能相当,“使用epoll就是为了高性能,就是要使用ET模式”这个说法是站不住脚的。个人倾向于使用LT模式,编程简单、安全。

    四、port模型
    port则和epoll非常接近,不需要前后的两次扫描,直接返回有事件的结果,可以象epoll一样绑定指针,不同点是
    (1)epoll可以返回多个事件,而port一次只返回一个(port_getn可以返回多个,但是在不到指定的n值时,等待直到达到n个)
    (2)port返回的结果会自动port_dissociate,如果要再次监控,需要重新port_associate
    这个就不多说了。

    可以看出select-->poll-->epoll/port的演化路线:
    (1)从readset、writeset等分离到 将读写事件集中到统一的结构
    (2)从阻塞操作前后的两次循环 到 之后的一次循环 
    到精确返回有事件发生的fd
    (3)从只能绑定fd信息,到可以绑定指针结构信息

    五、抽象接口
    综合以上多路复用函数的特点,可以进行统一的封装,这里给出我封装的接口,也算是给一个思路:

     virtual int init()=0;
     
    virtual int wait()=0;
     
    virtual void next_result()=0;
     
    virtual void delete_from_results(void data)=0;
     
    virtual void get_data(void event)=0;
     
    virtual int get_event(void event)=0;
     
    virtual int add_data(int fd,XPollData data)=0;
     
    virtual int delete_data(int fd,XPollData *data)=0;
     
    virtual int change_data(int fd,XPollData *data)=0;
     
    virtual int reset_data(int fd,XPollData *data)=0;

    使用的时候就是先init,再wait,再循环执行next_result直到空,每个result,使用get_data和get_event挨个处理,如果某个fd引起另一个fd关闭,调delete_from_results(除epoll,其它都直接return),处理完reset_data(select和port用,poll/epoll直接return)
    展开全文
  • 文章目录阻塞和非阻塞IO模型阻塞 io 模型 blocking IO非阻塞 io 模型 nonblocking IOIO多路复用模型select和pollepollIO多路复用模型应用场景 阻塞和非阻塞IO模型 操作系统在处理io的时候,主要有两个阶段: 1.等待...

    阻塞和非阻塞IO模型

    操作系统在处理io的时候,主要有两个阶段:

    • 1.等待数据传到io设备
    • 2.io设备将数据复制到user space

    我们一般将上述过程简化理解为:

    • 1.等到数据传到kernel内核space
    • 2.kernel内核区域将数据复制到user space(理解为进程或者线程的缓冲区)

    阻塞 io 模型 blocking IO

    最常用的也就是阻塞io模型。默认情况下,所有文件操作都是阻塞的。我们以套接字接口为例来讲解此模型,在进程空间调用recvfrom,其系统调用知道数据包到达并且被复制到进程缓冲中或者发生错误时才会返回,在此期间会一直阻塞,所以进程在调用recvfrom开始到它返回的整段时间都是阻塞的,因此称之为阻塞io模型。
    在这里插入图片描述
    应用层有数据过来,会调用recvfrom方法,但是这个时候应用层的数据还没复制到kernel中,将应用层数据复制到kerne这个阶段是需要时间的,所以recvfrom方法会阻塞,当内核中的数据准备好之后,recvfrom方法还不会返回,而是会发起一个系统调用将kernel中的数据复制到进程的缓冲区中,也就是user space,当这个工作完成之后,recvfrom才会返回并解除程序的阻塞。因此,阻塞io模型就是将这个两个过程合并在一起,一起阻塞。

    非阻塞 io 模型 nonblocking IO

    非阻塞模型则是将第一个过程的阻塞变成非阻塞,第二个阶段是系统调用,是必须阻塞的,所以非阻塞模型也是同步的,因为它们在kernel里的数据准备好之后,进行系统调用,将数据拷贝到进程缓冲区中。对于第一个阶段,也就是应用层数据到kernel的过程中,recvfrom会轮询检查,如果kernel数据没有准备还,就返回一个EWOULDBLOCK错误。不断的轮询检查,直到发现kernel中的数据准备好了,就返回,然后进行系统调用,将数据从kernel拷贝到进程缓冲区中。
    在这里插入图片描述

    IO多路复用模型

    **目的:**因为阻塞模型在没有收到数据的时候就会阻塞卡住,如果一次需要接受多个socket fd的时候,就会导致必须处理完前面的fd,才能处理后面的fd,即使可能后面的fd比前面的fd还要先准备好,所以这样就会造成客户端的严重延迟。为了处理多个请求,我们自然先想到用多线程来处理多个socket fd,但是这样又会启动大量的线程,造成资源的浪费,所以这个时候就出现了io多路复用技术。就是用一个进程来处理多个fd的请求。
    **应用:**适用于针对大量的io请求的情况,对于服务器必须在同时处理来自客户端的大量的io操作的时候,就非常适合
    在这里插入图片描述

    select和poll

    select和poll的工作流程类似:
    单个进程就可以同时处理多个网络连接的io请求(同时阻塞多个io操作)。基本原理就是程序呼叫select,然后整个程序就阻塞了,这时候,kernel就会轮询检查所有select负责的fd,当找到一个client中的数据准备好了,select就会返回,这个时候程序就会系统调用,将数据从kernel复制到进程缓冲区。
    在这里插入图片描述
    下图为select同时从多个客户端接受数据的过程
    虽然服务器进程会被select阻塞,但是select会利用内核不断轮询监听其他客户端的io操作是否完成。
    在这里插入图片描述
    poll的原理与select非常相似,差别如下:
    描述fd集合的方式不同,poll使用 pollfd 结构而不是select结构fd_set结构,所以poll是链式的,没有最大连接数的限制
    poll有一个特点是水平触发,也就是通知程序fd就绪后,这次没有被处理,那么下次poll的时候会再次通知同个fd已经就绪。

    select的缺点:

    • 1、单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当然可以更改数量,但由于select采用轮询的方式扫描文件描述符,文件描述符数量越多,性能越差;(在linux内核头文件中,有这样的定义:#define __FD_SETSIZE 1024)
    • 2、内核 / 用户空间内存拷贝问题,select需要复制大量的句柄数据结构,产生巨大的开销;
    • 3、select返回的是含有整个句柄的数组,应用程序需要遍历整个数组才能发现哪些句柄发生了事件;
    • 4、select的触发方式是水平触发,应用程序如果没有完成对一个已经就绪的文件描述符进行IO操作,那么之后每次select调用还是会将这些文件描述符通知进程。

    相比select模型,poll使用链表保存文件描述符,因此没有了监视文件数量的限制,但其他三个缺点依然存在。
    拿select模型为例,假设我们的服务器需要支持100万的并发连接,则在__FD_SETSIZE 为1024的情况下,则我们至少需要开辟1k个进程才能实现100万的并发连接。除了进程间上下文切换的时间消耗外,从内核/用户空间大量的无脑内存拷贝、数组轮询等,是系统难以承受的。因此,基于select模型的服务器程序,要达到10万级别的并发访问,是一个很难完成的任务。

    epoll

    由于epoll的实现机制与select/poll机制完全不同,上面所说的 select的缺点在epoll上不复存在。
    设想一下如下场景:有100万个客户端同时与一个服务器进程保持着TCP连接。而每一时刻,通常只有几百上千个TCP连接是活跃的(事实上大部分场景都是这种情况)。如何实现这样的高并发?
    在select/poll时代,服务器进程每次都把这100万个连接告诉操作系统(从用户态复制句柄数据结构到内核态),让操作系统内核去查询这些套接字上是否有事件发生,轮询完后,再将句柄数据复制到用户态,让服务器应用程序轮询处理已发生的网络事件,这一过程资源消耗较大,因此,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万个连接的句柄数据,内核也不需要去遍历全部的连接。

    参考:
    https://www.jianshu.com/p/1b4b3c738d8c
    https://blog.csdn.net/davidsguo008/article/details/73556811
    https://www.ibm.com/developerworks/cn/linux/l-cn-edntwk/index.html?ca=drs-

    IO多路复用模型应用场景

    • Netty
    • Redis
    展开全文
  • 2.非阻塞I/O多路复用模型 3.I/O多路复用模型的应用 1.传统阻塞I/O模型 传统的I/O阻塞模型中的“阻塞”的含义是指当前线程的阻塞性,下面用一图来说明这一阻塞I/O模型(读操作)。 看图中易知:整个I/O请求过程...

     

    目录

    1.传统阻塞I/O模型

    2.非阻塞I/O多路复用模型

    3.I/O多路复用模型的应用


    1.传统阻塞I/O模型

    传统的I/O阻塞模型中的“阻塞”的含义是指当前线程的阻塞性,下面用一图来说明这一阻塞I/O模型(读操作)。

    看图中易知:整个I/O请求过程中用户线程是阻塞的,所以cpu的利用率大打折扣。

    改进版本:上述过程中能否使得用户线程不是阻塞的呢?当然可以,见下图:

    上述版本可以认为是同步的非阻塞的I/O版本,但是用户线程还是一直处于读的忙碌的过程中,无法抽出身进行其他事务。

    现在提出新的需求,能否使得上述改进版本中的用户线程解放出来,使得用户线程可以去进行其他任务,当然是可以的,I/O多路复用模型解决了这个问题。

    2.非阻塞I/O多路复用模型

    I/O多路复用模型必须使用系统提供的select函数来监控当前读写状态,通过select函数的监控能力+reactor设计模式便可以实现非阻塞I/O多路复用模型,这样用户线程真正得到解放。如图所示:

    从图中可以看出,用户线程只需要先进行事件注册以及读请求就可以完成一次读事件,用户线程不阻塞并且可以去做其他任务。监控I/O的任务交给reactor完成,reactor需要不断轮询直到数据被准备好,最后还要通知用户线程现在数据可读,希望用户线程触发读操作读入数据。综上所述,I/O多路复用模型较传统轮询式非阻塞I/O模型将轮询任务转嫁给reactor从而实现用户线程的解放。

    3.I/O多路复用模型的应用

    最后说下I/O复用模型常见的使用场景。redis就是采取的I/O多路复用模型,我们知道redis的读写速度极快,研究表明速度可达100000QPS,这样的高速使得redis在单线程工作下依然能够取得优越的性能,那么redis是如何解决I/O读写时用户主线程的轮询或者阻塞问题呢(如第一点所述)?没错,redis就是使用了I/O多路复用模型,解放了主线程,使得redis仅在主线程这一个线程中依靠其高读写速度实现了对客户端多个请求的处理。

     

    展开全文
  • Redis之I/O多路复用模型实现原理

    千次阅读 2020-06-14 19:29:42
    在I/O多路复用之前我们先来看看Redis是怎么和客服... 首先,客户端 socket 会被设置为非阻塞模式,因为 Redis 在网络事件处理上采用的是非阻塞多路复用模型。 然后为这个 socket 设置 TCP_NODELAY 属性,禁用 Nag

    Redis的I/O多路复用模型有效的解决单线程的服务端,使用不阻塞方式处理多个client端请求问题。在看I/O多路复用知识之前,我们先来看看Redis是客服端怎么跟客服端建立连接的、单线程socket服务端为什么会存在I/O阻塞。

    Redis客户端连接

    Redis通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自client端的连接,当一个连接建立后,Redis 内部会进行以下一些操作:

    • 首先,客户端 socket 会被设置为非阻塞模式,因为 Redis 在网络事件处理上采用的是非阻塞多路复用模型。

    • 然后为这个 socket 设置 TCP_NODELAY 属性,禁用 Nagle 算法。

    • 然后创建一个可读的文件事件用于监听这个客户端 socket 的数据发送。

    阻塞I/O

    在socket连接中,一个服务器进程和一个客户端进行通信时,当一个client端向服务端写数据时,如果client端没有发送数据,那么服务端的read将一直阻塞,直到客户端write发来数据。在一个客户和服务器通信时没什么问题,当多个客户 与 一个服务器通信时,就存在问题了。如下图,两个客服端同时连接一个服务端进行写数据的时序图。

    从上图可以看出一个服务器进程和多个客户端进程通信的问题:

    • (1) client1和服务端建立连接后,服务端会一直阻塞于client1,直到client1客户端write发来数据才开始后面的操作。服务端阻塞期间,即使其他客服端client2的数据提前到来,也不能处理client2客服端的请求。

    • (2) 有一个严重的问题就是,如果客户端client1一直没有write数据到来,那么服务端service会一直阻塞,不能处理其他客户的服务。

    上面就是Redis通过Unix socket 的方式来接收来自client端的连接存在的I/O阻塞问题,而 I/O 多路复用就是为了解决服务端一直阻塞等待某一个client的数据到来,即使其他client的数据提前到来,也不会被处理的问题。

    I/O多路复用

    为什么Redis中要使用 I/O 多路复用这种技术呢?因为Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入 或 输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导,致整个进程无法对其它客户提供服务。而 I/O 多路复用就是为了解决这个问题而出现的。为了让单线程(进程)的服务端应用同时处理多个客户端的事件,Redis采用了IO多路复用机制。

    这里“多路”指的是多个网络连接客户端,“复用”指的是复用同一个线程(单进程)。I/O 多路复用其实是使用一个线程来检查多个Socket的就绪状态,在单个线程中通过记录跟踪每一个socket(I/O流)的状态来管理处理多个I/O流。如下图是Redis的I/O多路复用模型:

    #1.文件描述符(file descriptor):
        Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符。可以理解文件描述符是一个索引,这样,要操作文件的时候,我们直接找到索引就可以对其进行操作了。我们将这个索引叫做文件描述符(file descriptor),简称fd。

    如上图对Redis的I/O多路复用模型进行一下描述说明:

    • (1)一个socket客户端与服务端连接时,会生成对应一个套接字描述符(套接字描述符是文件描述符的一种),每一个socket网络连接其实都对应一个文件描述符。

    • (2)多个客户端与服务端连接时,Redis使用 I/O多路复用程序 将客户端socket对应的FD注册到监听列表(一个队列)中,并同时监控多个文件描述符(fd)的读写情况。当客服端执行accept、read、write、close等操作命令时,I/O多路复用程序会将命令封装成一个事件,并绑定到对应的FD上。

    • (3)当socket有文件事件产生时,I/O 多路复用模块就会将那些产生了事件的套接字fd传送给文件事件分派器。

    • (4)文件事件分派器接收到I/O多路复用程序传来的套接字fd后,并根据套接字产生的事件类型,将套接字派发给相应的事件处理器来进行处理相关命令操作。

    #例如:以Redis的I/O多路复用程序 epoll函数为例
        多个客户端连接服务端时,Redis会将客户端socket对应的fd注册进epoll,然后epoll同时监听多个文件描述符(FD)是否有数据到来,如果有数据来了就通知事件处理器赶紧处理,这样就不会存在服务端一直等待某个客户端给数据的情形。
    
    #(I/O多路复用程序函数有select、poll、epoll、kqueue)
    • (5)整个文件事件处理器是在单线程上运行的,但是通过 I/O 多路复用模块的引入,实现了同时对多个 FD 读写的监控,当其中一个client端达到写或读的状态,文件事件处理器就马上执行,从而就不会出现I/O堵塞的问题,提高了网络通信的性能。
    • (6)如上图,Redis的I/O多路复用模式使用的是 Reactor设计模式的方式来实现。

    总结:

    • (1) Redis的I/O多路复用程序函数有select、poll、epoll、kqueue。select 作为备选方案,由于其在使用时会扫描全部监听的文件描述符,并且只能同时服务 1024 个文件描述符,所以是备选方案。

    • (2) I/O 多路复用模型是利用select、poll、epoll函数可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉。当有一个或多个流有I/O事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll是只轮询那些真正发出了事件的流),依次顺序的处理就绪的流,这种做法就避免了大量无用的等待操作。

                                                                                                        2020年06月14日 晚 于北京记

    展开全文
  • 常用的多路复用模型总结

    千次阅读 2012-11-04 22:19:38
     本文对linux下几种常用的多路复用模型进行总结,不涉及其他操作系统如freeBSD等的多路复用技术。 2. 多路复用模型介绍  一般地,I/O多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)。分离器...
  • 从底层了解IO多路复用模型 前言 当我们去面试的时候,问到了 redis,nginx,netty他们的底层模型分别是什么? redis -> epoll nginx-> epoll netty-> epoll? 需要从操作系统的层面上来谈 BIO 当我们开机...
  • 网络模型(3)—— 多路复用模型
  • 根据上图模型,仿照Netty手写一个多路复用模型 MainThread.java package com.bjmashibing.system.io.testreactor; /** * @author: 马士兵教育 * @create: 2020-06-21 20:13 */ public class MainThread { ...
  • IO多路复用模型 IO:input和output,一般指数据的写入、数据的读取。IO主要分成两类:硬盘IO和网络IO,本内容主要针对网络IO。复用的含义可以理解为重复使用某个事物,而在本文,这个事物是指一个线程。因此,IO多路...
  • select、poll和epoll的区别和 IO多路复用模型讲解 IT生涯 2018-07-12 22:28:27 select、poll和epoll的区别 在linux没有实现epoll事件驱动机制之前,我们一般选择用select或者poll等IO多路复用的方法来实现并发...
  • 前言 在linux 没有实现epoll事件驱动机制之前,我们一般选择用select或者poll等IO多路复用...select()和poll() IO多路复用模型 select的缺点: 单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当...
  • Redis和多路复用模型

    2020-09-01 00:01:10
    后面会详细分析 在 I/O 多路复用模型中,最重要的函数调用就是 select,该方法的能够同时监控多个文件描述符的可读可写情况,当其中的某些文件描述符可读或者可写时,select方法就会返回可读以及可写的文件描述符个...
  • Linux :IO多路复用模型

    千次阅读 2016-03-08 14:47:52
    一、IO多路复用定义IO多路复用允许应用在多个文件描述符上阻塞,并在某一个可以读写时通知, 一般遵循下面的设计原则:、 IO多路复用:任何文件描述符准备好IO时进行通知 在文件描述符就绪前进行睡眠。 唤醒:哪个...
  • IO多路复用模型简图如下: 重点: 要明白,通信是通过 socket 来完成的,不懂的同学可以先去看一看 socket 网络编程。 首先,redis 服务端进程初始化的时候,会将 server socket 的 AE_READABLE 事件与连接应答...
  • 我们首先需要知道select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,...
  • 同步非阻塞I/O模型,利用selector多路复用器轮询为每一个用户创建连接,这样就不用阻塞用户线程,也不用每个线程忙等待。只使用一个线程轮询I/O事件,比较适合高并发,高负载的网络应用,充分利用系统资源快速处理...
  • select 和epoll只是用来提供多路复用的功能的,真正设置 非阻塞的socket还得用setsockopt,iocntl,fcntllibev模型: http://www.ibm.com/developerworks/cn/linux/l-cn-edntwk/libev代码示例: ... ...
  • 高并发服务器设计之多路复用模型

    千次阅读 2010-03-03 10:25:00
    多路复用的方式是真正实用的服务器程序,非多路复用的网络程序只能作为学习或着陪测的角色。本文说下个人接触过的多路复用函数:select/poll/epoll/port。kqueue的*nix系统没接触过,估计熟悉了上面四种,kqueue也...
  • 多路复用的方式是真正实用的服务器程序,非多路复用的网络程序只能作为学习或着陪测的角色。本文说下个人接触过的多路复用函数:select/poll/epoll/port。kqueue的*nix系统没接触过,估计熟悉了上面四种,kqueue也...
  •  一般地,I/O多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)。分离器对象可将来自事件源的I/O事件分离出来,并分发到对应的read/write事件处理器(Event Handler)。开发人员预先注册需要处理的事件...
  • 然后,才可以开启整个的IO多路复用模型的读流程。(1)进行select系统调用,查询可以读的连接。kernel会查询所有select的可查询socket列表,当任何一个socket中的数据准备好了,select就会返回。当用户进程调用了...
  • static void * epoll_init(struct event_base *base) { int epfd; struct epollop *epollop; /* Initialize the kernel queue.... * 2.6.8.) */ if ((epfd = epoll_create(32000)) == -1) { ...}

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 67,892
精华内容 27,156
关键字:

多路复用模型