在上一篇中,我们深入探讨了TCP/IP协议的11种状态,理解这些状态对我们编写服务器的时候有很大的帮助,但一般写服务器都是使用C/Java语言,因为这些语言对高并发的支持特别好。我们写的这些简单的服务器主要是为了深入学习TCP/IP协议、IO操作以及Python中协程的原理。在上一篇中也提到非阻塞这个概念,在这一篇中,我们继续深入探讨IO模型,因为理解IO操作对我们深入学习异步编程有很大帮助。所以在这一节中我们主要是从Linux内核态和用户态的层面来考虑IO操作时会发生什么样的事情,Linux内核会做什么。

一、常见5种IO模型

1.阻塞IO模型

    阻塞IO模型图如下:

 

  说明:

  (1).当上层应用程序调用recv系统调用时,进程会从用户态切换到内核态;如果此时对方没有发送数据来(内核缓冲区没有数据),那么应用程序将会被阻塞(默认行为,被Linux内核阻塞)。

  (2).当对方把数据发送过来了之后,Linux内核会自动把数据copy到用户空间的缓冲区中,然后进程恢复执行,执行下一步操作!

2.非阻塞IO模型

  非阻塞IO模型图如下:

  说明:

  (1). 进程中需要将套接字设置为非阻塞模式;

  (2). 进程会一直调用recv()函数去接收数据,如果缓冲区中没有数据,那么进程也不会被阻塞,只是recv()会返回一个错误码(EWOULDBLOCK)

  (3). 进程会不断轮询有没有数据到来。这样会造成进程忙等待。大量消耗CPU资源。因此很少使用,一般和select或epoll机制一起使用。

3.IO复用模型

  IO复用模型图如下:

 

  说明:

  (1). 进程使用select机制(该机制由Linux内核支持,避免了进程忙等待),目的是去轮询文件描述符的状态变化

  (2). 当select管理的文件描述符没有变化时,进程也会被阻塞;但是使用select可以管理多个文件描述符,效率就提高了。这就不像非阻塞模型中,去轮询recv()。

  (3). select可以看成一个管家,使用select来管理多个IO。

    一旦检测到一个或多个IO有我们感兴趣的事件发生时,select函数将返回,返回值是检测到的事件个数。

  (4). select函数可以设置超时时间, 这样可以避免进程处于干等待状态,长期僵死

  (5). 和非阻塞IO模型相比,select IO复用模型相当于提前阻塞了。当有数据来到时,可以直接调用recv()来获取数据。

4.信号驱动IO

  信号驱动IO模型图如下:

  说明:

  (1). 在上层应用程序中会建立SIGIO信号的处理程序。当缓冲区有数据来到时,内核会发送数据到上层应用程序。

  (2). 当上层应用程序收到信号后,调用recv()函数,因为缓冲区有数据,recv()函数一般不会被阻塞。

  (3). 这种模型用的比较少,属于典型的"拉模型",即,上层应用程序需要调用recv()函数把数据拉进来。

5.异步IO模型

  异步IO模型图如下:

  说明:

  (1). 上层应用程序调用aio_read函数,同时会提交一个应用层的缓冲区给内核写入数据;调用完毕后,应用程序不会被阻塞,可以继续执行其他任务。

  (2). 当数据过来时,Linux内核主动把数据从内核空间copy到用户空间,然后再给应用程序发送一个信号,告诉进程数据已经复制过去了,你赶紧处理数据吧。

  (3). 这是一个"推模式",效率非常之高,应用程序有异步处理的能力(在Linux内核的辅助下,进程在处理其他任务的同时,也可以进行IO通讯)。与信号驱动IO模型相比,应用程序不需要调用recv()来接收数据!

  (4). 异步IO是什么?

    应用程序在处理其他事情的同时,还可以接收数据。

小结:通过对比五种IO模型,我们可以很明显发现他们的区别以及效率,一般在开发中IO复用模型和异步IO模型是最常用的模型!

   五种模型的对比图:

   

转载于:https://www.cnblogs.com/fangtaoa/p/9045851.html

Python高级网络编程系列之第二篇相关推荐

  1. Python高级网络编程系列之第一篇

    在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...

  2. Python高级网络编程系列之基础篇

    一.Socket简介 1.不同电脑上的进程如何通信? 进程间通信的首要问题是如何找到目标进程,也就是操作系统是如何唯一标识一个进程的! 在一台电脑上是只通过进程号PID,但在网络中是行不通的,因为每台 ...

  3. python高级网络编程_Python高级网络编程系列之基础篇

    一.Socket简介 1.不同电脑上的进程如何通信? 进程间通信的首要问题是如何找到目标进程,也就是操作系统是如何唯一标识一个进程的! 在一台电脑上是只通过进程号PID,但在网络中是行不通的,因为每台 ...

  4. python高级网络编程_python高级编程——网络编程(二)

    UDP 概念和介绍 UDP --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议. UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并 不能保证它们能到达目的地. U ...

  5. Python Socket网络编程(二)局域网内和局域网与广域网的持续通信

    目录 前言 IP地址 简介 公有IP 私有IP 局域网之间网络通信 前提 功能描述 源码 运行结果 局域网与广域网网络通信 前提 源码 结语 前言 本系列博客是笔者学习Python Socket的过程 ...

  6. Python Socket网络编程(一)初识Socket和Socket初步使用

    目录 前言 网络编程 实质 IP地址和端口 数据传输协议 协议 Socket 概念 套接字 socket对象方法 初步使用 功能 源码 运行结果 结语 前言 本系列博客是笔者学习Python Sock ...

  7. CoreOS Fest 系列之第二篇: Systemd、Go、Calico、Sysdig

    本文讲的是CoreOS Fest 系列之第二篇: Systemd.Go.Calico.Sysdig,[编者的话]在 CoreOS Fest 第二天的会议中,演讲者展示了多个开源项目和工具,包括 Sys ...

  8. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

  9. Python之网络编程(TCP套接字与UDP套接字)

    文章目录 基于tcp的套接字 实现目标 tcp服务端源码 tcp客户端源码 tcp效果实现 基于udp的套接字 udp作用介绍 udp服务端源码 udp客户端源码 udp效果实现 用udp实现一个时间 ...

最新文章

  1. 黑客提交漏洞先获感谢后被举报 网络安全行业或现标志性事件
  2. Object-C 入门介绍
  3. lis3dh 三轴加速度计 运动检测 中断配置实现
  4. 自定义滚动条Js简版
  5. Linux ping不通百度的解决方法
  6. 第六十节,文本元素标签
  7. 摘要算法与加密(以MD5算法为例)
  8. ftp限流java,FTP流量限制的方法
  9. 流式数据分析_流式大数据分析
  10. 【LeetCode+51nod】股票低买高卖N题
  11. html给背景架渐变,JS和CSS实现渐变背景特效的代码
  12. C++算法学习(力扣:1003. 检查替换后的词是否有效)
  13. Javascript第二章中While/do..while循环第三课
  14. 工业和能源1994-2019年省级面板数据
  15. 使用Javascript 实现 分享到 新浪微博 QQ 空间等
  16. SQLServer2000数据库导入步骤
  17. 个人总结的新手看房买房注意事项,有遗漏的地方请各位同学帮忙补充
  18. 展讯7731C_M Android6.0 充电指示灯实现(一)------关机充电实现【转】
  19. Schedule(贪心,任务调度)
  20. oracle escape关键字用法

热门文章

  1. linux下kerberos教程
  2. 精益业务分析宣言解读
  3. 解决打包软链接打包失败问题
  4. Rhel6.0部署Oracle10g报错相关问题记录
  5. Spring 使用注解方式进行事务管理
  6. linux 配置 java 环境变量
  7. Redmine Feedback
  8. wince中的hook(钩子)用法
  9. canvas画柱状图 和饼图
  10. Linux文本过滤与处理命令