带着问题阅读
1、什么是同步异步、阻塞非阻塞
2、有几种IO模型,不同模型之间有什么区别
3、不同IO模型的应用场景都是什么

同步和异步、阻塞和非阻塞

同步和异步

广义上讲同步异步描述的是事件中发送方和接收方之间的关系

  • 当发送方必须依赖接收方的响应结果(无论正确与否)才能进行下一步操作,则两者间的关系是同步的。
  • 当发送方不必依赖接收方的响应即可继续执行,则两者间的关系是异步的。在异步关系中,发送方可能根本不在意接收方的返回信息,也可能接收方通过事件、回调的形式来通知发送方结果。

即在同步关系中,发送方和接收方的步调是一致的,而异步关系中则没有必要。

快递员派送一件必须当面签收的贵重物品,快递员必须在客户签字后才能确认送达,快递员和客户的关系就是同步。
快递员派送普通物件,直接放到快递柜里,客户取出后系统自动确认送达,快递员和客户的关系就是异步。

阻塞和非阻塞

阻塞和非阻塞形容的是事件单个参与者的状态

  • 当参与者因为某些条件没有满足而无法执行下一步动作,只能原地等待,那么该参与者就陷入了阻塞。
假设有一条单行车道,有一天道路中央由于暴雨积水严重无法通过,那么经过这条路的车辆便陷入了阻塞状态。

四种组合

  • 同步阻塞:发送方发起调用后,必须等待接收方的完成响应,且在此期间发送方不能执行任何动作。

    顾客去银行柜台存钱,在柜员存入流程完成之前,顾客必须在柜台前等候流程结束。
  • 同步非阻塞:发送方发起调用后,如接收方不能马上完成,可先返回给发送方一个未完成状态,发送方收到后可自行判断继续等待还是先执行其他动作再做轮询查看。

    顾客去买奶茶,奶茶不能马上做好,就给了顾客一张单号。顾客可以在附近逛逛,每隔一会儿主动过来询问好了没有。
  • 异步阻塞:发送方发起调用后无需等待接收方任何响应,但由于接收方的动作影响发送方的状态,发送方无法执行其他动作。(实践中通常没有该应用场景)

  • 异步非阻塞:发送方发起调用后无需等待接收方任何响应,自由执行其他动作。

    顾客去吃饭排队,小程序扫码以后就可以去别处逛。当排到该顾客时,小程序推送就餐消息给顾客。

UNIX IO模型

通常所说IO模型为网络IO模型,一个网络IO主要包含几个阶段:应用进程监听某个端口,等待数据从网络中到达网卡缓冲区,数据到达后CPU收到信号将数据转移到内核缓冲区,然后将数据从缓冲区复制到应用进程缓冲区。依据监听方式和数据复制方式的不同,UNIX IO主要分为5种IO模型。

阻塞IO

阻塞IO是最基础的IO模型,应用进程监听端口后就一直陷入阻塞状态,直到有数据到达。如下图所示,应用程序调用recvfrom后即陷入阻塞状态,直到CPU将数据拷贝到用户空间后,应用程序才能继续执行。

非阻塞IO

非阻塞IO允许应用程序调用recvfrom时立即返回,在数据没有就绪时,返回状态为EWOULDBLOCK,这时应用程序可继续执行,但需要不断发起轮询(polling)判断数据是否就绪。

非阻塞IO仅针对数据未就绪时是非阻塞的,在数据拷贝过程还是阻塞的。

IO多路复用

通过使用select/poll/epoll,应用进程可以同时等待多个设备的数据状态。应用程序在发起select/poll/epoll调用时会进入阻塞状态,但当其监听的任一个文件描述符数据就绪即可返回,应用程序即可对对应描述符发起recvfrom调用,拷贝应用数据。

IO多路复用带来的好处:
在上述的阻塞和非阻塞IO,如果要对多个描述符进行监听,则需要同时开启多个进程/线程。
通过select/poll/epoll可以使单个进程/线程具备监听多个连接的能力。
只要当IO事件发生时处理相应描述符即可,因此也称为事件驱动IO。

信号驱动IO

应用程序通过为SIGIO信号注册一个信号关联函数监听文件描述符,调用注册后应用程序可立即返回继续执行。当描述符数据就绪时,通过产生SIGIO信号发起对应用程序信号关联函数的调用,应用程序可通过recvfrom进行数据拷贝。

异步IO

异步IO模式下,应用程序触发系统调用后可立即返回,内核在数据拷贝完成后再对应用程序发出信号,触发应用程序逻辑。

异步IO与信号驱动IO的区别是:
- 信号驱动IO产生信号后,应用程序仍然需要阻塞读取数据到应用程序空间。
- 异步IO数据拷贝的过程也是由CPU进行的,直到拷贝完成才通知应用程序,做到全程非阻塞。

模型比较

通过前面的描述我们可以看出,前四种IO模型只有在等待数据阶段有区别,在拷贝数据时都会进入阻塞状态。而异步IO在应用程序的整个阶段都是非阻塞的。前四种IO都属于同步IO,最后一种属于异步IO。

POSIX把同步IO操作定义为导致进程阻塞直到IO完成的操作,反之则是异步IO。

select/poll/epoll

  • select

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

    select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。

    select的缺点是

    • select对于单个进程能够见识的文件描述符数量存在限制,32位环境为1024,64位为2048。
    • select返回后仅直到有IO事件产生,具体到哪个描述符只能进行O(n)级别的轮询。
  • poll

    int poll (struct pollfd *fds, unsigned int nfds, int timeout);

    不同与select使用三个位图来表示三个fdset的方式,poll使用一个 pollfd的指针实现,同时poll没有最大数量限制。

  • epoll

    int epoll_create(int size);//创建一个epoll的句柄epfd,size用来告诉内核这个监听的数目一共有多大
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);//对指定fd添加删除监听事件
    int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);//等待句柄上的事件

    epoll操作需要三个函数才完成创建,epoll可以直接返回哪些描述符产生了事件,因此复杂度时O(1)的。

    epoll有两种工作方式:

    • LT(level trigger)模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。
    • ET(edge trigger)模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。

    为什么要有两种模式:

    如果采用LT模式的话,系统中一旦有大量你不需要读写的就绪文件描述符,它们每次调用epoll_wait都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率。而采用ET模式的话,当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你。

参考

Unix 网络IO模型介绍的更多相关文章

  1. unix网络io模型

    阻塞I/O(bloking I/O) 阻塞IO的特点就是在IO执行的两个阶段(recvfrom和数据从内核空间转移到用户空间)都被block了 非阻塞I/O(non-bloking I/O)   非阻 ...

  2. python网络编程——网络IO模型

    1 网络IO模型介绍 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:    (1)同步阻塞IO(Blocking IO):即传统的IO模型.    (2)同步非阻塞IO(Non-bl ...

  3. Python socket编程之IO模型介绍(多路复用*)

    1.I/O基础知识 1.1 什么是文件描述符? 在网络中,一个socket对象就是1个文件描述符,在文件中,1个文件句柄(即file对象)就是1个文件描述符.其实可以理解为就是一个“指针”或“句柄”, ...

  4. 5种网络IO模型

    5种网络IO模型(有图,很清楚)   同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到 ...

  5. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  6. {python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块

    python之IO多路复用 阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 ...

  7. Socket-IO 系列(一)Linux 网络 IO 模型

    Socket-IO 系列(一)Linux 网络 IO 模型 一.基本概念 在正式开始讲 Linux IO 模型前,先介绍 5 个基本概念. 1.1 用户空间与内核空间 现在操作系统都是采用虚拟存储器, ...

  8. (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...

  9. python全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

随机推荐

  1. 大型情感类技术连续剧-徒手撸一个 uTools(二)

    前言 上篇手把手教你实现一个支持插件化的 uTools 工具箱我们介绍过了如何通过 electron 实现 utools 的插件功能体系,并按照 utools 的交互和设计做出了一套可以支持插件化的桌 ...

  2. PyCharm 2020.1 激活教程

    本文内容皆为作者原创,如需转载,请注明出处:https://www.cnblogs.com/xuexianqi/p/14967434.html 免责声明:本方法只做学习研究之用,不得用于商业用途 若经 ...

  3. DDoS防护方式以及产品

    导航: 这里将一个案例事项按照流程进行了整合,这样查看起来比较清晰.部分资料来自于Cloudflare 1.DDoS介绍 2.常用DDoS攻击 3.DDoS防护方式以及产品 4.Cloudflare ...

  4. Linux中重要目录详解

    Linux重要目录详解 / 根目录,第一层目录,所有其他目录的根,一般根目录下只存放目录.包括:/bin, /boot, /dev, /etc, /home, /lib, /mnt, /opt, /p ...

  5. Docker搭建Prometheus+grafana监控系统

    一.Prometheus简介 1.简介 Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB). Prometheus使用Go语言开发,是Google BorgM ...

  6. Sql Server 查询正在执行的sql信息和锁定事务

    执行中的sql SELECT [Spid] = session_Id, ecid, [Database] = DB_NAME(sp.dbid), [User] = nt_username, [Stat ...

  7. 为什么要鼓励小型企业使用CRM系统

    如果你是一家小公司的管理者,我相信你必须对工作流程.客户.市场销售.市场营销推广等业务流程进行总体规划和管理方法,这往往会使你的心有馀而力不足,引起 繁忙.心有馀而力不足.交流受到阻碍.管理方法和这样 ...

  8. apache 2.2 静态文件目录的配置

    引用 #禁止使用proxy_ajp代理的目录: ProxyPass /sns/images/ ! #使用proxy_ajp代理:下面的配置,是把所有目录全用代理(当然,还会跟上面的禁用配置组合成完整的 ...

  9. Spring Boot中文文档(官方文档翻译 基于1.5.2.RELEASE)

    作者:Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch, Andy Wilkinson, Marcel Overdijk, ...

  10. 11 shell中内置关键字[[]]:检查条件是否成立

    0.[[]] [] (())的对比 1.[[]]支持正则表达式 0.[[]] [] (())的对比 [[ ]] 对数字的比较不友好,所以使用 if 判断条件时,建议用(())来处理整型数字,用[[]] ...