Unix 网络IO模型介绍
带着问题阅读
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模型介绍的更多相关文章
- unix网络io模型
阻塞I/O(bloking I/O) 阻塞IO的特点就是在IO执行的两个阶段(recvfrom和数据从内核空间转移到用户空间)都被block了 非阻塞I/O(non-bloking I/O) 非阻 ...
- python网络编程——网络IO模型
1 网络IO模型介绍 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-bl ...
- Python socket编程之IO模型介绍(多路复用*)
1.I/O基础知识 1.1 什么是文件描述符? 在网络中,一个socket对象就是1个文件描述符,在文件中,1个文件句柄(即file对象)就是1个文件描述符.其实可以理解为就是一个“指针”或“句柄”, ...
- 5种网络IO模型
5种网络IO模型(有图,很清楚) 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到 ...
- python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
- {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) 五 ...
- Socket-IO 系列(一)Linux 网络 IO 模型
Socket-IO 系列(一)Linux 网络 IO 模型 一.基本概念 在正式开始讲 Linux IO 模型前,先介绍 5 个基本概念. 1.1 用户空间与内核空间 现在操作系统都是采用虚拟存储器, ...
- (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...
- python全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
随机推荐
- rust漫游 - 写时拷贝 Cow<'_, B>
rust漫游 - 写时拷贝 Cow<'_, B> Cow 是一个写时复制功能的智能指针,在数据需要修改或者所有权发生变化时使用,多用于读多写少的场景. pub enum Cow<'a ...
- PowerMock 支持gRPC的Mock Server实现
PowerMock是一个Mock Server的实现,它同时支持HTTP与gRPC协议接口的Mock,并提供了灵活的插件功能. 这个工具面向于前后端.测试等对有接口Mock需求的开发人员,也可以作为一 ...
- POJ 3984 迷宫(BFS)
入门BFS,第一次做,部分借鉴了大牛的 #include <iostream> #include <cstdio> #include <queue> using n ...
- CRM系统对企业管理的作用有多大?
随着市场经济的发展,对任何行业的企业来说,客户都是非常重要的一个部分.CRM系统帮助企业做到以客户为中心,它可以根据客户的具体要求进行跟进和反馈,在很大程度上提高公司的客户服务水平和客户满意度,进而提 ...
- ExtJs4学习(五)最基本的Ext类
Ext类是ExtJs中最常见.最基础的一个类,它是一个全局对象,封装了所有类.单例和 Sencha 库所提供的实用方法. 大多数用户界面组件在一个较低的层次嵌套在命名空间中, 但是提供的许多常见的实用 ...
- SpringMVC的注解关键词解释
SpringMVC的注解关键词解释 @Controller控制器定义 和Struts1一样,Spring的Controller是Singleton的.这就意味着会被多个请求线程共享.因此,我们将控制器 ...
- 2020年MySQL数据库面试题总结(50道题含答案解析)
1.MySQL 中有哪几种锁? (1)表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最 高,并发度最低. (2)行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最 ...
- PHP递归创建多级目录(一道面试题的解题过程)(转)
今天看到一道面试题,要写出一个可以创建多级目录的函数: 我的第一个感觉就是用递归创建,具体思路如下: function Directory($dir){ if(is_dir($dir) || @m ...
- buu crypto 凯撒?替换?呵呵!
一. 以为是简单的凯撒加密,但是分析Ascill表,发现毫无规律,意味着要爆破出所有可能.只能用在线工具来弄了,脚本是不可能写的(狗头) 找到了,但是提交不成功,需要变成小写,用脚本转换一下,同时很坑 ...
- mDNS知识
1.域名系统(Domain Name System,缩写:DNS)是互联网的一项服务.它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.DNS使用TCP和UDP端口53. ...