• 网络I/O_04 IO模型


    一.本质

    1.本质

            用户角度:网卡-网卡之间通信

            内核角度:socket-socket之间数据输入输出

    2.与文件IO区别

    (1)数据位置:

            文件:数据是已确定在磁盘上的,但是

            网络:只是连接了一个端口,是否有数据到达,未确定

    (2)读取步骤:

            网络IO:需要先查,确定有数据才发起真正IO操作,2步

            文件IO:直接读,1步

    3.问题与解决

    (1)核心问题:查

            假设一个服务同时连接多个socket

            Q:怎么判断什么时候socket有数据到达?

            Q:是哪一个socket的数据到达?

    (2)解决办法:

            方案1:轮询:        

                    用户进程层面轮询,拿fd一个一个扔给内核帮忙查,查到了告诉我,我去拷贝

                    内核层面轮询,用户进程扔一堆给内核,让内核轮询,哪个有结果了,通知去拷贝       (select,poll)

            方案2:基于信号(事件) epoll,异步

    小知识:

            A.每个socket连接都返回一个fd,linux一切皆文件

            B.用户进程无法直接问网卡是否有数据,需要拿sokcet连接分配的fd问内核,内核帮我们去查,得到内核返回的结果,再进行下一步

            C.用户进程问内核,用户态到内核态切换,剩下交给内核处理

    二、IO模型

    1.IO生命周期

            一次IO生命周期一般涉及两个阶段与两个对象

    (1)两个阶段与两个对象

            对象:用户进程和内核进程,

            阶段:网卡-内核阶段,内核-用户阶段(针对接收,发送反之)

    (2)周期

            发送数据: 用户空间->内核->网卡-网络

            接收数据: 网络->网卡->内核->用户空间

            A.用户进程创建一个socket连接,然后开始把fd传给内核,开始监听数据

            B.socket有一个接收缓冲区:recive buffer和写缓冲区writh buffer, 一个数据包到达网卡(NIC)时,首先会以DMA(存储器直接访问, 允许在 外部设备存储器 之间直接读写数据)的方式把网卡的帧写入到内存,然后向CPU发送一个软中断,告诉内核去处理下,内核这是就会用select,poll,epoll_wait等来收包

            C.内核监测到哪个fd有数据包到了,再通知用户,用户再调用read()系统调用读取数据

      (3)接收的具体流程是:先等后取

            A:用户进程在创建socket连接时会返回一个fd,然后将fd加入到内核监听集合fds,有数据包到,内核会收到软中断信号,去遍历fds,看是哪个fd数据到达,然后标记好通知用户进程,

    B:用户进程等到通知后,再次发起read()系统调用。内核去拷贝该socket的数据到用户进程缓存区,再通知用户进程,可以访问数据了

    (4)小结:网络IO生命周期,先等后取

    2.IO模型

            如何批量处理socket数据到达,常见5种IO模型:

            阻塞IO

            非阻塞IO

            多路复用IO

            信号驱动IO

            异步IO

    (1)阻塞IO:(linux默认所有IO都是阻塞的)

            kernel会检查socket是否有数据到达,如果fd数据还没到达,kernel会一直阻塞,直到有数据才返回。

            这是同步阻塞(BIO)模型

    (2)非阻塞IO

            kernel检查fd的数据到了没,如果fd数据还没到达,返回error给kernel。然后过段时间,kernel再来问,不停轮询,直到有数据,结果返回给用户。

    这是同步非阻塞(NIO)模型:是用户进程不停循环fds问kernel有没数据。

    (3)多路复用IO

            多个IO可以注册到一个复用器上,用户进程问kernel,一组fds的数据到了没,fds数据都没到达,kernel一等。任一fd数据到达,返回结果通知用户进程拷贝这个fd的数据。

    循环fds有:select,poll这两种多路复用模型。

     另一种:epoll则是把每个fd都注册一个回调函数,当一个fd有数据到达,回调通知这个fd的进程,过来读数据

    (4)信号驱动IO

            在信号驱动IO模型中,当⽤户线程发起⼀个IO请求操作,会给对应的socket注册⼀个信号函数,然后⽤户线程会继续执⾏,当内核数据就绪时会发送⼀个信号给⽤户线程,⽤户线程接收到信号之后,便在信号函数中调⽤IO读写操作来进⾏实际的IO请求操作。这个⼀般⽤于UDP中,对TCP套接⼝⼏乎是没⽤的,原因是该信号产⽣得过于频繁,并且该信号的出现并没有告诉我们发⽣了什么事情

    该模型很少使用

    这是同步非阻塞(NIO)模型

    前4中都可以归结为:同步IO

    从整个IO过程来看,他们都是顺序执行的,进程主动等待且向内核检查状态

    (5)异步IO

            当进程发起一个IO操作,马上得到内核返回,可以先去处理其他事情了,注意数据可能不是马上得到;内核会一直查询fd数据是否到达,到达之后,顺便把数据拷贝到用户和内核都能访问得内存共享缓存区,然后告诉用户进程,可以直接拿到数据了。

    实际上是信号驱动+拷贝数据。

    这是异步非阻塞模型(AIO)

    读写操作由内核完成,完成后内核将数据放到指定用户进程的缓冲区,通知应用程序来取

            扩展:

            Windows的IOCP实现了真正的异步IO

            Linux系统下,异步IO模型在2.6版本才引入,目前并不完善,其底层实现仍使用epoll

            大多数的高并发服务器端的程序,一般都是基于Linux系统的,因此大多还采用IO多路复用模型

    3.Java 中的BIO,NIO,AIO

    (1)BIO:同步阻塞IO

            卡那里的问题:用户进程-内核-socket

            A. 用户进程卡在内核这里(同步)

            B. 内核卡在socket这里(阻塞)

    (2)NIO: I/O 多路复用模型

            卡那里的问题:用户进程-内核-socket

            A. 用户进程卡在内核这里(同步)

            B. 内核不卡在socket这里(非阻塞,kernel定时轮询)

            select,poll

    (3)AIO:异步非阻塞

    异步 IO 是基于事件和回调机制实现

    epoll

    先理解这几个概念:

    异步:用户进程-(内核-socket)(用户马上可以得到内核查询socket有没数据的结果,然后去处理其他事情)

    4.同步和异步:

    (1)用户有没第一时间获取查询结果。用户进程-内核之间

            同步:用户拿fd问内核,这个fd有数据了没?内核查看fd的数据,有,返回给用户。若内核查到fd没数据,让用户进程等着,先不返回。定期再次查fd,循环往复,直到有数据才返回给用户进程。用户进程收到消息,再次发起读取系统调用,让内核拷贝数据到用户缓存区。

            异步:用户拿fd问内核,这个fd有数据了没?内核查看fd的数据,有,返回给用户,没有返回err。用户若得到err,就先不等了,先去处理其他事情。剩下得事情交给内核了(fd数据到达,会主动通知用户)

    (2)区别:

    返回结果得时机和复制fd数据的时机

    同步是内核告诉用户进程数据来了。用户需再次发起调用,内核去复制fd的数据到用户缓存区

    异步是内核直接fd的数据都给复制到了用户缓存区了,然后通知用户进程好了(缓存共享技术)。

    5.阻塞和非阻塞:

    (1)内核有没第一时间获取查询结果。内核-fd之间

    阻塞:是指内核查fd数据是否到达,有数据才返回结果,否则一直在等待;

    非阻塞:是指内核查fd数据是否到达,有数据返回结果,没数据返回err

  • 相关阅读:
    UGeek大咖说 | 精彩回顾:京东商城可观测性体系的落地与实践
    Linux下NFS共享存储安装详细步骤
    C语言-入门-extern和头文件(十六)
    进阶课2——语音分类
    GB/T28181-2016基于RTP的视音频数据封装和技术实现
    D. Maximum Sum on Even Positions(最大连续字段和)
    【云原生 • Kubernetes】一文掌握 k8s 包管理工具 Helm
    Web大学生网页作业成品——抗击疫情网站设计与实现(HTML+CSS)
    Linux驱动开发——(五)内核中断
    [附源码]计算机毕业设计基于springboot的网上点餐系统
  • 原文地址:https://blog.csdn.net/u012728971/article/details/126867867