带着问题阅读
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. Spring Boot下的一种导出Excel文件的代码框架

    1.前言 ​ 在Spring Boot项目中,将数据导出成Excel格式文件是常见的功能.与Excel文件导入类似,此处也用代码框架式的方式实现Excel文件导出,使得代码具有可重用性,并保持导出数据 ...

  2. 远程连接MySQL错误“plugin caching_sha2_password could not be loaded”的解决办法

    远程连接MySQL错误"plugin caching_sha2_password could not be loaded"的解决办法 问题描述: 今天在阿里云租了一个服务器,当我用 ...

  3. oscp-缓冲区溢出(持续更新)

    环境准备 Windows7虚拟机(我选了IE8,其实也没什么关系) 微软官方下载地址 These virtual machines expire after 90 days. We recommend ...

  4. 使用 Docker 秒速搭建多版本 PHP 开发环境

    目录 目标 下载 代理设置 配置环境 PHP 7.2.x,占用本地端口 8081 PHP 5.6.x,占用本地端口 8082 端口映射 local.php72.com -> 127.0.0.1: ...

  5. flex中Button事件中的e.target

    关于flex中的Button事件中的e.target. 今天想在事件中调用模块中的对象通过e.target获取单击的这个Button对象,但是可能是使用var btn:Button = e.targe ...

  6. Linux查找占用的端口,并杀死进程

    我要使用4040端口,但是被其他的程序占用了 1. 查找占用的程序 netstat -apn | grep 4040 最后一项显示的是pid和对应的名称 2. 杀掉对应的进程,彻底杀死进程 kill ...

  7. linux学习之路第三天

    开机,重启和用户登陆注销 关机&重启命令 shutdown shutdown -h now :表示立即关机 shutdown -h 1 :表示一分钟后关机 shutdown -r now :表 ...

  8. Spring中如何使用自定义注解搭配@Import引入内外部配置并完成某一功能的启用

    文章背景 有一个封装 RocketMq 的 client 的需求,用来提供给各项目收.发消息,但是项目当中常常只使用收或者发消息的单一功能,而且不同的项目 group 等并不相同而且不会变化,可以在项 ...

  9. phpstudy后门复现遇到的坑

    这几天遇到一个phpstudy后门的站之前没复现过,结果遇到了深坑记录一下 首先用这个脚本去验证是没问题的: https://github.com/NS-Sp4ce/PHPStudy_BackDoor ...

  10. C语言:获取汉字的编码

    #include <stdio.h> #include <locale.h> #include <wchar.h> int main() { setlocale(L ...