网络I/O模型

人多了,就会有问题。web刚出现的时候,光顾的人很少。近年来网络应用规模逐渐扩大,应用的架构也需要随之改变。C10k的问题,让工程师们需要思考服务的性能与应用的并发能力。

网络应用需要处理的无非就是两大类问题,网络I/O数据计算。相对于后者,网络I/O的延迟,给应用带来的性能瓶颈大于后者。网络I/O的模型大致有如下几种:

  • 同步模型(synchronous I/O)

    • 阻塞I/O(bloking I/O)
    • 非阻塞I/O(non-blocking I/O)
    • 多路复用I/O(multiplexing I/O)
    • 信号驱动式I/O(signal-driven I/O)
  • 异步I/O(asynchronous I/O)

网络I/O的本质是socket的读取,socket在linux系统被抽象为流,I/O可以理解为对流的操作。这个操作又分为两个阶段:

  1. 等待流数据准备(wating for the data to be ready)。
  2. 从内核向进程复制数据(copying the data from the kernel to the process)。

对于socket流而已,

  • 第一步通常涉及等待网络上的数据分组到达,然后被复制到内核的某个缓冲区。
  • 第二步把数据从内核缓冲区复制到应用进程缓冲区。

I/O模型

举个简单比喻,来了解这几种模型。网络IO好比钓鱼,等待鱼上钩就是网络中等待数据准备好的过程,鱼上钩了,把鱼拉上岸就是内核复制数据阶段。钓鱼的人就是一个应用进程。

阻塞I/O(bloking I/O)

阻塞I/O是最流行的I/O模型。它符合人们最常见的思考逻辑。阻塞就是进程 "被" 休息, CPU处理其它进程去了。在网络I/O的时候,进程发起recvform系统调用,然后进程就被阻塞了,什么也不干,直到数据准备好,并且将数据从内核复制到用户进程,最后进程再处理数据,在等待数据到处理数据的两个阶段,整个进程都被阻塞。不能处理别的网络I/O。大致如下图:

 
1.png

这就好比我们去钓鱼,抛竿之后就一直在岸边等,直到等待鱼上钩。然后再一次抛竿,等待下一条鱼上钩,等待的时候,什么事情也不做,大概会胡思乱想吧。

阻塞IO的特点就是在IO执行的两个阶段都被block了

非阻塞I/O(non-bloking I/O)

在网络I/O时候,非阻塞I/O也会进行recvform系统调用,检查数据是否准备好,与阻塞I/O不一样,"非阻塞将大的整片时间的阻塞分成N多的小的阻塞, 所以进程不断地有机会 '被' CPU光顾"。

也就是说非阻塞的recvform系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error。进程在返回之后,可以干点别的事情,然后再发起recvform系统调用。重复上面的过程,循环往复的进行recvform系统调用。这个过程通常被称之为轮询。轮询检查内核数据,直到数据准备好,再拷贝数据到进程,进行数据处理。需要注意,拷贝数据整个过程,进程仍然是属于阻塞的状态。

 
2.png

我们再用钓鱼的方式来类别,当我们抛竿入水之后,就看下鱼漂是否有动静,如果没有鱼上钩,就去干点别的事情,比如再挖几条蚯蚓。然后不久又来看看鱼漂是否有鱼上钩。这样往返的检查又离开,直到鱼上钩,再进行处理。

非阻塞 IO的特点是用户进程需要不断的主动询问kernel数据是否准备好。

多路复用I/O(multiplexing I/O)

可以看出,由于非阻塞的调用,轮询占据了很大一部分过程,轮询会消耗大量的CPU时间。结合前面两种模式。如果轮询不是进程的用户态,而是有人帮忙就好了。多路复用正好处理这样的问题。

多路复用有两个特别的系统调用selectpoll。select调用是内核级别的,select轮询相对非阻塞的轮询的区别在于---前者可以等待多个socket,当其中任何一个socket的数据准好了,就能返回进行可读,然后进程再进行recvform系统调用,将数据由内核拷贝到用户进程,当然这个过程是阻塞的。多路复用有两种阻塞,select或poll调用之后,会阻塞进程,与第一种阻塞不同在于,此时的select不是等到socket数据全部到达再处理, 而是有了一部分数据就会调用用户进程来处理。如何知道有一部分数据到达了呢?监视的事情交给了内核,内核负责数据到达的处理。也可以理解为"非阻塞"吧。

 
3.png

对于多路复用,也就是轮询多个socket。钓鱼的时候,我们雇了一个帮手,他可以同时抛下多个钓鱼竿,任何一杆的鱼一上钩,他就会拉杆。他只负责帮我们钓鱼,并不会帮我们处理,所以我们还得在一帮等着,等他把收杆。我们再处理鱼。多路复用既然可以处理多个I/O,也就带来了新的问题,多个I/O之间的顺序变得不确定了,当然也可以针对不同的编号。

多路复用的特点是通过一种机制一个进程能同时等待IO文件描述符,内核监视这些文件描述符(套接字描述符),其中的任意一个进入读就绪状态,select, poll,epoll函数就可以返回。对于监视的方式,又可以分为 select, poll, epoll三种方式。

了解了前面三种模式,在用户进程进行系统调用的时候,他们在等待数据到来的时候,处理的方式不一样,直接等待,轮询,select或poll轮询,第一个过程有的阻塞,有的不阻塞,有的可以阻塞又可以不阻塞。当时第二个过程都是阻塞的。从整个I/O过程来看,他们都是顺序执行的,因此可以归为同步模型(asynchronous)。都是进程主动向内核检查。

异步I/O(asynchronous I/O)

相对于同步I/O,异步I/O不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。I/O两个阶段,进程都是非阻塞的。

 
4.png

比之前的钓鱼方式不一样,这一次我们雇了一个钓鱼高手。他不仅会钓鱼,还会在鱼上钩之后给我们发短信,通知我们鱼已经准备好了。我们只要委托他去抛竿,然后就能跑去干别的事情了,直到他的短信。我们再回来处理已经上岸的鱼。

同步和异步的区别

通过对上述几种模型的讨论,需要区分阻塞和非阻塞,同步和异步。他们其实是两组概念。区别前一组比较容易,后一种往往容易和前面混合。对于同步和异步而言,往往是一个函数调用之后,是否直接返回结果,如果函数挂起,直到获得结果,这是同步;如果函数马上返回,等数据到达再通知函数,那么这是异步的路程。

至于阻塞和非阻塞,则是函数是否让线程挂起不再往下执行。通常同步阻塞,异步非阻塞。什么情况下是异步阻塞呢?即函数调用之后并没有返回结果而注册了回调函数,非阻塞的情况下,函数也马上返回,可是如果此时函数不返回,那么此时就是阻塞的状态,等数据到达通知函数,依然是异步的过程。

区分阻塞和非阻塞只要区分函数调用之后是否挂起返回就可以了,区分异步和同步,则是函数调用之后,数据或条件满足之后如何通知函数。等待数据返回则是同步,通过回调则是异步。

 
5.png

对于同步模型,主要是第一阶段处理方法不一样。而异步模型,两个阶段都不一样。这里我们忽略了信号驱动模式。这几个名词还是容易让人迷惑。

本文所讨论的IO模型来自大名鼎鼎的《unix网络编程:卷1套接字联网API》。单台服务器中的linux系统。分布式的环境或许会不一样。个人学习笔记,参考了网络上大多数文章,做了一点小测试

copy自:https://www.jianshu.com/p/55eb83d60ab1

网络I/O模型---同步异步阻塞非阻塞之惑的更多相关文章

  1. 简明网络I/O模型---同步异步阻塞非阻塞之惑

    转自:http://www.jianshu.com/p/55eb83d60ab1 网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之 ...

  2. 谈谈对不同I/O模型的理解 (阻塞/非阻塞IO,同步/异步IO)

    一.关于I/O模型的问题 最近通过对ucore操作系统的学习,让我打开了操作系统内核这一黑盒子,与之前所学知识结合起来,解答了长久以来困扰我的关于I/O的一些问题. 1. 为什么redis能以单工作线 ...

  3. Python番外之 阻塞非阻塞,同步与异步,i/o模型

    1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步:      所谓同步,就 ...

  4. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  5. (转)同步异步,阻塞非阻塞 和nginx的IO模型

    同步异步,阻塞非阻塞 和nginx的IO模型  原文:https://www.cnblogs.com/wxl-dede/p/5134636.html 同步与异步 同步和异步关注的是消息通信机制 (sy ...

  6. python并发编程之IO模型 同步 异步 阻塞 非阻塞

    IO浅谈 首先 我们在谈及IO模型的时候,就必须要引入一个“操作系统”级别的调度者-系统内核(kernel),而阻塞非阻塞是跟进程/线程严密相关的,而进程/线程又是依赖于操作系统存在的,所以自然不能脱 ...

  7. 转:IO模型-- 同步和阻塞,异步和非阻塞的区别

    源地址 http://hi.baidu.com/deep_pro/item/db0c581af1c1f17e7b5f2534 这些词之间的区别难倒了很多人,还有什么同步阻塞, 同步非阻塞, 异步阻塞, ...

  8. 深入了解几种IO模型(阻塞非阻塞,同步异步)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zk3326312/article/details/79400805一般来说,Linux下系统IO主要 ...

  9. 哪5种IO模型?什么是select/poll/epoll?同步异步阻塞非阻塞有啥区别?全在这讲明白了!

    系统中有哪5种IO模型?什么是 select/poll/epoll?同步异步阻塞非阻塞有啥区别? 本文地址http://yangjianyong.cn/?p=84转载无需经过作者本人授权 先解开第一个 ...

随机推荐

  1. java反射机制基础

    java反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和 属性:这种动态获取信息以及动态调用对象方法的功能称为j ...

  2. 基于Systick系统时钟延时的LED闪烁灯

    1.回顾我们的51 单片机编程,当我们需要做系统延迟的时候,最常采用的一种方式就是使用for 循环的空语句等待来实现. 当然,在STM32 里面也可以这么实现.但是在STM32 的Cortex 内核里 ...

  3. C++程序设计方法3:函数重写

    派生类对象包含从基类继承类的数据成员,他们构成了“基类子对象”基类中的私有成员,不允许在派生类成员函数中被访问,也不允许派生类的对象访问他们:真正体现基类私有,对派生类也不开放其权限:基类中的公有成员 ...

  4. DP专题:划分数问题

    一.这个专题有什么用 练练DP 练练组合数学 ...... 二.正题 此类问题有如下几种形态: 1. 将n划分成若干正整数之和的划分数.2. 将n划分成k个正整数之和的划分数.3. 将n划分成最大数不 ...

  5. 使用8.0版本jdbc驱动连接数据库操作

    转自:https://blog.csdn.net/qq_41734885/article/details/80562815 首先,我居然不能用navicat客户端连接上mysql8.0数据库报1251 ...

  6. python字符串面试题:找出一个字符串中第一个字母和最后一个字符是第一次重复,中间没有重复且最长的子串

    1.给出任意一个字符串,打印一个最长子串字符串及其长度,如果有相同长度的子字符串,都要一起打印出来,该子字符串满足以下条件, 第一个字母和最后一个字符是第一次重复 这个子字符串的中间字母没有重复 这个 ...

  7. PAT基础6-7

    6-7 统计某类完全平方数 (20 分) 本题要求实现一个函数,判断任一给定整数N是否满足条件:它是完全平方数,又至少有两位数字相同,如144.676等. 函数接口定义: int IsTheNumbe ...

  8. C语言中字符输入问题

    先上例题,一道太水太水的题, http://acm.hdu.edu.cn/showproblem.php?pid=1170 让做一个简单的计算器.然而入坑了. #include<stdio.h& ...

  9. ImportError: No module named _tkinter on macos

    MAC OS 10.11.6 lMacBook-Pro:~ xiaomilbq$ python Python 2.7.14 (default, Sep 22 2017, 00:05:22) [GCC ...

  10. MyBatis架构与源码分析<资料收集>

    1.架构与源码分析 :https://www.cnblogs.com/luoxn28/p/6417892.html .https://www.cnblogs.com/wangdaijun/p/5296 ...