前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >I/O 模型如何演进及 I/O 多路复用是什么?

I/O 模型如何演进及 I/O 多路复用是什么?

作者头像
五月君
发布于 2019-08-13 15:07:27
发布于 2019-08-13 15:07:27
7490
举报
文章被收录于专栏:Nodejs技术栈Nodejs技术栈

人生如同故事。重要的并不在有多长,而是在有多好。——塞涅卡

I/O 是 Input/Ouput 的缩写,即输入输出端口,是信息处理系统(例如计算机)与外部世界(可能是人类或另一信息处理系统)之间的通信。输入是系统接收的信号或数据,输出则是从其发送的信号或数据。

I/O 先修知识

I/O 也是一个很宽泛的词,每个设备都会有一个专用的 I/O 地址,用来处理自己的输入输出信息。对于服务端研发的童鞋相信 网络 I/O磁盘 I/O 这些词,也需并不陌生,一次 API 接口调用、向磁盘写入日志信息,其实就是在跟 I/O 打交道。一次 I/O 操作分为等待资源使用资源两个阶段,以下分别进行介绍。

阻塞与非阻塞 I/O

阻塞与非阻塞 I/O 是对于操作系统内核而言的,发生在等待资源阶段,根据发起 I/O 请求是否阻塞来判断。

阻塞 I/O:这种模式下一个用户进程在发起一个 I/O 操作之后,只有收到响应或者超时才可进行处理其它事情,否则 I/O 将会一直阻塞。以读取磁盘上的一段文件为例,系统内核在完成磁盘寻道、读取数据、复制数据到内存中之后,这个调用才算完成。阻塞的这段时间对 CPU 资源是浪费的。

非阻塞 I/O:这种模式下一个用户进程发起一个 I/O 操作之后,如果数据没有就绪,会立刻返回(标志数据资源不可用),此时 CPU 时间片可以用来做一些其它事情。

同步与异步 I/O

同步与异步 I/O 发生在使用资源阶段,根据实际 I/O 操作来判断。

同步 I/O:应用发送或接收数据后,如果不返回,继续等待(此处发生阻塞),直到数据成功或失败返回。

异步 I/O:应用发送或接收数据后立刻返回,数据写入 OS 缓存,由 OS 完成数据发送或接收,并返回成功或失败的信息给应用。Node.js 就是典型的异步编程例子。

用户空间与内核空间

操作系统为了支持多个应用同时运行,需要保证不同进程间相对独立、内核的安全,那就不能谁都能来操作了,因此操作系统将内存空间划分为用户空间、内核空间两部分。用户空间存放用户程序代码和数据,而内核空间存放内核代码和数据。

其实一直以来对于用户空间与内核空间的界限划分还是有点傻傻分不清的感觉,最近读到了一篇文章 解读I/O多路复用技术 https://www.jianshu.com/p/db5da880154a,上面有段描述,分别从 OSI 七层模型图 网际网协议族 来看待用户空间与内核空间的分界线,此处引用下图片,总结性的说明下,更详细的推荐去作者网站看下原文讲解。

OSI 七层模型与网际网协议族图

可以看到这里以传输层做了边界划分,传输层之上为用户空间(Web 客户端、浏览器、FTP 这些都属于上三层),下四层为内核空间,例如传输层的 TCPUDP 协议就对应到了内核空间。

操作系统 I/O 模型演进

操作系统的 I/O 模型分为:阻塞 I/O、非阻塞 I/O、I/O 复用、信号驱动 I/O、异步 I/O 五种,本节参考 Unix 网络编程一书,图片也引自本书中,以下分别进行介绍。

同步阻塞 IO

从应用程序开始系统调用->数据就绪进行拷贝->拷贝结束,这之间应用程序都处于等待状态,不能做其它事情,直到将数据拷贝到用户空间或出错才返回,我们称之为阻塞 I/O 模式。

同步非阻塞 IO

相比于同步阻塞 I/O 模式,同步非阻塞 I/O 在每次调用之后,如果数据没有就绪就会立即返回,之后重复调用来检查 I/O 操作是否就绪,这对 CPU 资源是一个极其浪费的操作,直到数据就绪将数据从内核拷贝到用户空间,返回成功指示给到应用程序。

Read:就是一种实现,通过重复轮询 I/O 来判断。

IO 多路复用

链接(Socket)并发大的情况,上面两种就不适合了,前面一个处理不完,后面就只能干等,这里就用到了 I/O 多路复用技术,下图所示相比较前两种,分为了两步,先进行 select 数据就绪后,在调用 recvfrom 进行真正的 I/O 读写操作。它的高级之处还在于能够一个线程同时处理多个 Socket。

什么是 I/O 多路复用?

【面试指南】请解释下什么是 I/O 多路复用?

有必要先弄清这个概念,这里的 I/O 通常指网络 I/O,多路指多个 Socket 链接,复用指操作系统进行运算调度的最小单位线程。整体意思也就是多个网络 I/O 复用一个或少量的线程来处理 Socket。关于 I/O 多路复用的多种实现,继续参考下文。

I/O 多路复用的四种实现

I/O 多路服用有多种实现模式:selectpollepollkqueue

  • select

通过轮询检查在文件描述符上设置的标识位来进行判断,select 的轮询相当于在数据库中查找一条记录没有建立索引,对所有的 socket 进行全部遍历,这对 CPU 是浪费的。另外 select 还有一个限制,对于单个进程所能打开的文件描述符最大只能是 1024,那么基于 select 的轮询技术最多也只能很好的处理 1000 并发的吞吐量,可以查看 上一个10年,著名的C10K并发连接问题

  • poll

poll 和 select 在实现上没有本质的区别,相比较 select,poll 基于链表来实现,没有了最大链接 1024 的限制。但是当文件描述符多了之后,每次调用都会对链接进行线性遍历,性能还是十分低下的。

  • epoll

是 linux 下效率最高的 I/O 事件通知机制,没有最大链接限制,通过 callbak 回调通知机制,不在是每次调用都对链接进行线性遍历,这样就不会随着文件描述符的增加导致效率下降。

在 1GB 内存的机器上能监听大约 10 万个端口,远超过 select 的 1024 限制,具体可以在服务器上查看 cat/proc/sys/fs/file-max

  • kqueue

与 epoll 类似,仅存于 FreeBSD(一种类UNIX操作系统)。

信号驱动 IO

仅在 Unix 上支持,与 I/O 多路复用相比避免了 select 的阻塞轮询。应用程序进行系统调用后立即返回,处理其它事物,在数据就绪之后系统会发送一个 SIGIO 信号到应用程序,应用进程开始读取数据。

异步 IO 模型

异步 I/O 模型是目前最理想的一种形式,应用程序发起系统调用后无需等待直接返回当前调用状态,进行后续的其它任务,结果由内核完成 I/O 操作之后通过回调通知到我们的应用程序,中间没有阻塞过程。

在 Linux2.6 之后增加了异步 I/O 的实现方式 AIO,但是很少系统能够实现。

白话风格讲解 I/O 模型的演进

上面讲解了几种 I/O 模型的演进,如果不明白的,我们通过白话风格(小明与妹子的邂逅)讲解操作系统 I/O 模型是什么?之间的区别是什么?

故事标题:小明与妹子的邂逅 故事情节:小明在校园一次文艺晚会上邂逅了一位妹子,在只得知妹子名字、手机号的情况下,经过几天的苦苦追寻,历经千山万水,终得美人归! 演员介绍:男一号@小明、女一号@妹子、串场@门卫大爷

  • 同步阻塞 I/O 模式

小明电话相约妹子在校门口,然后小明很专一、不见到妹子不回家,期间没有做任何事情,一直在等待!

  • 同步非阻塞 I/O 模式

小明电话相约妹子在校门口,妹子还没准备好(出门前化妆几小时。。。),这时候的小明很执着,每隔一会儿给妹子发个信息直到妹子准备好了。

  • I/O 多路复用模式
    • select 小明电话相约妹子在校门口,委托门卫select大爷帮忙,select大爷很敬业每出去一个人都会进行询问,但是select大爷有个限制最多只能询问1024个。
    • poll poll类似于select功能,不同的是poll大爷没有1024限制,可以一直坚持,但是当poll大爷超过1024,询问的越来越多之后就显得越来越精疲力尽了。
    • epoll 小明电话相约妹子在校门口,委托门卫epoll大爷帮忙,epoll大爷不在是每个询问,规定每个人出入校门必须带上学生证,这样opoll大爷就是知道哪个是小明的女神了,epoll大爷找到女神之后在电话通知小明。
  • 信号驱动 I/O 模式

小明电话相约妹子在校门口,此时妹子回复说我还没准备好(出门前化妆几小时。。。),这个时候小明也没去,而是先去干其它事情了,等妹子准备好之后电话通知小明,我已经准备好了,小明这个时候才去校门口等着和妹子的约会。

  • 异步 I/O 模式

小明告诉妹子我们在校园门口相约,之后小明没有在那干等了,而是先回宿舍休息会或者和朋友在打会球等等,妹子到校门口之后电话通知小明,我已经来啦。

Select VS Epoll

【面试指南】如果问到轮询技术的实现一般也会考察 select 和 epoll 的区别?

在操作方式上区别

  • select 采用了线性遍历来查找,链接多了之后可以想象一下在一个诺大的数组中每次通过遍历来锁定一个链接,是多么的消耗性能。
  • epoll 则不需要遍历,采用的是回调机制,可以看作一个 HashTable,来锁定一个对象是很快的。

文件描述符限制

  • 对于文件描述符(最大连接数)select 限制为 1024。
  • epoll 则没有这个限制,通常在 1G 内存的机器上所能支持的连接数为 10W 左右。

对于操作系统的支持

从操作系统支持上来看,目前流行的高性能 Web 服务器 Nginx 是基于 epoll 来实现高并发,当然如果你的链接很小的情况下区别还是不大的 select 也能满足,如果是大流量、高并发情况 epoll 目前还是首选模型。

Reference

  • 书籍《UNIX 网络编程》
  • https://blog.csdn.net/gzh0222/article/details/9227393
  • https://www.jianshu.com/p/db5da880154a
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Nodejs技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
搞懂I/O多路复用及其技术
高性能是每个程序员的追求,无论写一行代码还是做一个系统,都希望能够达到高性能的效果。高性能架构设计主要集中在两方面:
BUG弄潮儿
2021/01/05
6810
超详细的I/O多路复用概念、常用I/O模型、系统调用等介绍
I/O多路复用,I/O就是指的我们网络I/O,多路指多个TCP连接(或多个Channel),复用指复用一个或少量线程。串起来理解就是很多个网络I/O复用一个或少量的线程来处理这些连接。
lyb-geek
2021/09/23
2.1K0
I/O的内核原理与5种I/O模型
我们都知道unix世界里、一切皆文件、而文件是什么呢?文件就是一串二进制流而已、不管socket、还是FIFO、管道、终端、对我们来说、一切都是文件、一切都是流、在信息交换的过程中、我们都是对这些流进行数据的收发操作、简称为I/O操作(input and output)、往流中读出数据、系统调用read、写入数据、系统调用write、不过话说回来了、计算机里有这么多的流、我怎么知道要操作哪个流呢?做到这个的就是文件描述符、即通常所说的fd(file descriptor)、一个fd就是一个整数、所以对这个整数的操作、就是对这个文件(流)的操作、我们创建一个socket、通过系统调用会返回一个文件描述符、那么剩下对socket的操作就会转化为对这个描述符的操作、不能不说这又是一种分层和抽象的思想、
小柒吃地瓜
2020/04/21
2.1K0
I/O的内核原理与5种I/O模型
聊聊同步与异步、阻塞与非阻塞、I/O模型
程序员:假如我们执行A,B两个IO操作的时候,如果必须等待A完成后才能执行B那么这个就是
咻一咻
2020/05/29
1.3K0
这次答应我,一举拿下 I/O 多路复用!
要想客户端和服务器能在网络中通信,那必须得使用 Socket 编程,它是进程间通信里比较特别的方式,特别之处在于它是可以跨主机间通信。
小林coding
2021/03/30
7410
这次答应我,一举拿下 I/O 多路复用!
深入学习IO多路复用select/poll/epoll实现原理
Linux 服务器处理网络请求有三种机制,select、poll、epoll,本文打算深入学习下其实现原理。
涂明光
2022/11/27
1.8K2
python3--IO模型,阻塞,非阻塞,多路复用,异步,selectors模块
结论:协程任务开启,并不一定会执行,它需要I/O(阻塞)才能执行,上面代码的time.sleep(1)模拟了I/O(阻塞)
py3study
2018/08/02
1.1K0
IO多路复用的三种机制Select,Poll,Epoll
select、poll 和 epoll 都是 Linux API 提供的 IO 复用方式。
用户5807183
2019/08/01
1.1K0
IO多路复用的三种机制Select,Poll,Epoll
看一遍就理解:IO模型详解
大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~
捡田螺的小男孩
2021/12/01
1.4K0
看一遍就理解:IO模型详解
但是,I/O多路复用中是如何判断文件“可读”/“可写”的?
那么,操作系统内核到底是如何判断某个文件描述符“可读”/“可写”呢?在达到相关状态后,是如何“立即”通知到应用程序的呢?本文在探究这个问题。
Piper破壳
2025/05/08
870
框架篇:linux网络I/O+Reactor模型
网络I/O,可以理解为网络上的数据流。通常我们会基于socket与远端建立一条TCP或者UDP通道,然后进行读写。单个socket时,使用一个线程即可高效处理;然而如果是10K个socket连接,或者更多,我们如何做到高性能处理?
潜行前行
2020/12/11
1.1K0
框架篇:linux网络I/O+Reactor模型
万字图解| 深入揭秘IO多路复用
     通过前面的文章我们已经了解了「数据包从HTTP层->TCP层->IP层->网卡->互联网->目的地服务器」以及「数据包怎么从网线到进程,在被应用程序使用」涉及的知识。      本文将继续介绍网络编程中的各种细节和IO多路复用的原理。
公众号 云舒编程
2024/01/25
4.4K2
万字图解| 深入揭秘IO多路复用
Redis为什么这么快之多路复用
当别人问我们Redis这么快的时候,很多小白都只会简简单单的回答,因为Redis它是基于内存存储的,使用内存存储数据,可以避免频繁的进行写盘操作,大大降低响应时间。这个确实是一个原因,但回答的还是不够面。起码在这里还得回答上高效的数据结构以及IO网络多路复用的设计架构。
一个风轻云淡
2023/09/15
4230
各种IO复用模式之select,poll,epoll,kqueue,iocp分析
上篇文章,我们介绍了Java IO框架的演变,其实编程语言的IO实现是依赖于底层的操作系统,如果OS内核不支持,那么语言层面也无能为力。任何一个跨平台的编程语言,一定是能够在不同操作系统之间选择使用最优的IO模型,那么不同平台的io策略都有哪些实现呢?本篇文章我们就来了解一下。
我是攻城师
2018/12/17
8.2K0
你应该知道的五种IO模型
linux操作系统包含了五种IO模型,各种上层编程语言或者网络编程框架的上层实现都是基于操作系统的这些IO实现来实现的。
春哥大魔王
2019/11/21
4840
IO 多路复用
为了讲多路复用,当然还是要跟风,采用鞭尸的思路,先讲讲传统的网络 IO 的弊端,用拉踩的方式捧起多路复用 IO 的优势。
敖丙
2021/07/27
9670
IO 多路复用
高并发的秘诀:I/O多路复用
👆点击“博文视点Broadview”,获取更多书讯 程序员编写代码执行I/O操作最终都逃不过文件这个概念。 在Unix/Linux世界中,文件是一个很简单的概念,作为程序员我们只需要将其理解为一个N字节的序列就可以了: b1, b2, b3, b4, ....... , bN 实际上,所有的I/O设备都被抽象为了文件这个概念,一切皆文件(Everything is  File),磁盘、网络数据、终端,甚至进程间通信工具管道pipe等都被当成文件对待。 所有的I/O操作也都可以通过文件读写来实现,这一抽
博文视点Broadview
2023/05/19
4140
高并发的秘诀:I/O多路复用
阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO 一锅端
本文会涉及到阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO等几个知识点,知识点虽然不难但经常容易搞混,这次带领大家再回顾一遍。
码农编程进阶笔记
2021/07/20
4130
阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO 一锅端
I/O模型
目前我们网络所面临的依然是高并发的问题,就像某cat双11时的情况,瞬间的并发量是惊人的,当然我们会有很多种方法去解决这个问题,本文我们谈论的是单台服务器,如何提高自己对并发请求的处理能力。要想解决这个问题,我们需要先理清楚Unix和类Unix系统的I/O模型。
用户2645267
2018/08/04
5150
I/O多路复用,从来没遇到过这么明白的文章
很多对技术有追求的读者朋友,做到一定阶段后都希望技术有所精进。有些读者朋友可能会研究一些中间件的技术架构和实现原理。比如,Nginx为什么能同时支撑数万乃至数十万的连接?为什么单工作线程的Redis性能比多线程的Memcached还要强?Dubbo的底层实现是怎样的,为什么他的通信效率非常高?
用户7927337
2021/06/25
7950
I/O多路复用,从来没遇到过这么明白的文章
相关推荐
搞懂I/O多路复用及其技术
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档