Netty快速入门(01)Linux I/O模型介绍
Netty简述
Netty是一个高性能的网络编程框架。
上面提到了几个关键的字眼,高性能,网络编程,框架。这些概括Netty的本质。
Netty是一个NIO客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化并简化了TCP和UDP套接字服务器等网络编程。
“快速简便”并不意味着最终的应用程序会受到可维护性或性能问题的影响。Netty经过精心设计,具有丰富的协议,如FTP,SMTP,HTTP以及各种二进制和基于文本的传统协议。因此,Netty成功地找到了一种在不妥协的情况下实现易于开发,性能,稳定性和灵活性的方法。
先来简单看一下Netty官网的架构图:

从图中可以看出,Netty的架构分为三块,核心(Core),通信服务(Transport Services)还有各种协议(Protocol Support)。我们想象将来要学习的内容都和这些有关系。通过架构图对其有个基本印象。
Linux I/O 模型
在Linux中,将I/O模型分为五种类型:
阻塞式 I/O 模型
非阻塞式 I/O 模型
I/O 复用
信号驱动式 I/O
异步 I/O
Linux中的I/O流程概括来说可以分为两步:
1、等待数据准备好(Waiting for the data to be ready)
2、从内核向进程复制数据(Copying the data from the kernel to the process)
来看下面的图片:

从上面的流程可以看出,首先是内核空间把数据从硬件(磁盘)中读到内核空间的缓冲区中,进行这一步操作时,数据处于内核态,通过磁盘驱动器,把数据从磁盘读到内核缓冲区来。下一步是把数据从内核缓冲区拷贝到用户空间的缓冲区,数据由内核态变为用户态。
知识普及:Linux中的程序大致运行在两个空间,自己的程序运行在用户空间,用户空间的权限有限,相对的另外一个空间是内核空间,比如驱动程序或者一些核心的系统调用都是在内核空间完成的。我们的I/O操作当在一个用户空间做系统调用的时候,数据会自动从用户态变到内核态来进行操作,完成了以后再从内核空间拷贝到用户空间。这种状态的切换是为了保证安全。比如在我们32位的操作系统中,大部分是4G的内存,一般前面一个G主要是内核态使用,后面三个G是用户态使用。
阻塞式 I/O 模型

阻塞式I/O是我们最常见的一种IO,当我们发起一个IO请求之后,开始进行系统调用,数据变为内核态,这两个阶段是一直处于阻塞的。数据开始从磁盘拷贝到内核空间,处理完后再从内核空间拷贝到应用空间,数据变为用户态。这整个的过程涉及到的所有程序线程都是在等待状态。比如我们Java普通的Socket编程,就是这样一个流程。整个过程中数据没有完成前,接收方都是出于等待状态,这就是阻塞式IO模型。明显可见效率不会高。
非阻塞式 I/O 模型

这种方式的特点是调用的时候不会等待(也就是不会阻塞),系统如果没有数据,就会立刻告诉你现在没数据,会立刻返回,然后由调用方自己去问现在有没有,如果没有就下次再问有没有,相当于不断去轮询结果,直到某个时刻被告知有结果了,这个时候数据已经从磁盘拷贝到内核空间了,数据也处于内核态,就差最后从内核态拷贝到用户空间,但是,从内核空间拷贝到用户空间,让数据从内核态变为用户态,这个过程在非阻塞式 I/O 模型中,也是阻塞的!所以效率也不会太高。
I/O 复用模型

复用的意思是,系统一次去查看多个io的进度,看哪一个有了结果,对于有结果的,就开始执行下面从内核空间拷贝到用户空间的操作,这个模型和上面非阻塞式 I/O 模型的区别是,非阻塞式 I/O 模型一次只看一个结果好了没有,而IO复用模型一次可以查看多个,一次监控一批系统调用好了没有,这是复用模型的特点。在一定程度上,能提高一些效率。
信号驱动式 I/O 模型

在Linux系统中,有一种信号机制,也就是说调用方可以注册一个信号,当系统调用完成之后,可以通知这个信号,那注册信号的人就会知道这个请求已经完成了,这种信号机制应用在IO当中就是信号驱动式IO。这样就不是查看结果是否好了,而是被通知的一种方式。不过通知后,从内核态到用户态这个过程还是阻塞的。纯异步的模型就是下面要说的这个。
异步 I/O模型

这种模型是真正的纯异步的IO模型,当开始系统调用,数据从磁盘读到内核空间,并且从内核态已经拷贝到了用户态之后,整个流程已经完成了,然后在进行回调,通知调用方。主要的区别在于不是在内核空间中完成了就通知,而是由内核空间到了用户空间后再通知,没有任何阻塞的过程,是一种更加彻底的异步IO。
各种I/O模型之间的比较

阻塞式IO就是发起调用之后,就一直阻塞,在等着,直到整个IO完成。在这个过程当中,进程是不能干任何事情的。都在等待。
非阻塞式IO就是,进程会主动去问好了没,好了没,好了没。。。直到得到回复好了,然后发起读请求,把数据从内核空间拷贝到用户空间。这个过程是阻塞的。
IO复用模型,就是每次都查看多个结果好了没,如果发现n个当中有一两个有了结果,就返回,有结果的这些开始拷贝。
信号驱动式IO模型,就是等数据拷贝到内核空间再通知,前面这段时间可以做别的事情,等内核空间准备好了,通知,再把数据从内核空间拷贝到用户空间。
异步IO模型,就是发起调用后就彻底不管了,等数据好了后从内核空间拷贝到用户空间了,再进行通知,整个过程没有阻塞的步骤。
从比较重来看,异步IO从理论上来看是最好的,不存在任何阻塞的时间,系统资源理论上可以得到充分利用。
同步VS异步
lPOSIX标准将同步I/O和异步I/O定义为:
同步I/O操作:导致请求进程阻塞,直到I/O操作完成。
异步I/O操作:不导致请求进程阻塞。
从定义上看,只有最后的异步IO模型是真正的异步,前面四种都达不到真正的异步。但是目前来看,纯异步的IO一直都不太成熟,比较混乱,没有一个标准的解决方案。用的最多的还是IO复用模型,这个是目前为止比较成熟的一个模型。
在Java中,我们用的最多的Socket网络编程,就是阻塞式IO模型,后来的NIO就是IO复用模型,在Java中不支持信号驱动模型。Java的NIO2.0,也叫AIO,提供了纯异步的IO模型,但是现在的异步IO模型还不是很成熟,所以用的最多的就是NIO,也就是IO复用模型。
推荐书籍《Unix网络编程》,推荐理由:网络编程的经典之作,经历了十年左右,内容基本变化不大,原理性书籍,是网络编程的必看之书。
本文由博客一文多发平台 OpenWrite 发布!
Netty快速入门(01)Linux I/O模型介绍的更多相关文章
- Netty快速入门(05)Java NIO 介绍-Selector
Java NIO Selector Selector是Java NIO中的一个组件,用于检查一个或多个NIO Channel的状态是否处于可读.可写.如此可以实现单线程管理多个channels,也就是 ...
- Netty快速入门(08)ByteBuf组件介绍
前面的内容对netty进行了介绍,写了一个入门例子.作为一个netty的使用者,我们关注更多的还是业务代码.也就是netty中这两种组件: ChannelHandler和ChannelPipeline ...
- Netty快速入门(03)Java NIO 介绍-Buffer
NIO 介绍 NIO,可以说是New IO,也可以说是non-blocking IO,具体怎么解释都可以. NIO 1是在JSR51里面定义的,在JDK1.4中引入,因为BolckingIO不支持高并 ...
- Netty快速入门(09)channel组件介绍
书接上回,继续介绍组件. ChannelHandler组件介绍 ChannelHandler组件包含了业务处理核心逻辑,是由用户自定义的内容,开发人员百分之九十的代码都是ChannelHandler. ...
- Netty快速入门(06)Netty介绍
前面简单的介绍了Java I/O 和NIO,写了示例程序. Java I/O是阻塞的,为了让它支持多个并发,就要针对每个链接启动线程,这种方式的结果就是在海量链接的情况下,会创建海量的线程,就算用线程 ...
- 网络应用框架Netty快速入门
一 初遇Netty Netty是什么? Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.可扩展协议的服务器和客户端 ...
- Netty快速入门(10)Reactor与Netty
Reactor模式 Reactor是1995年由道格拉斯提出的一种高性能网络编程模式.由于好多年了,当时的一些概念与现在略有不同,reactor模式在网络编程中是非常重要的,可以说是NIO框架的典型模 ...
- ETCD快速入门-01 ETCD概述
1.ETCD概述 1.1 ETCD概述 etcd是一个高可用的分布式的键值对存储系统,常用做配置共享和服务发现.由CoreOS公司发起的一个开源项目,受到ZooKeeper与doozer启发而 ...
- docker快速入门01——docker安装与简单应用
1.docker简介 Docker 是一个开源的应用容器引擎,Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化 ...
随机推荐
- Python--day71--分页功能
分页功能代码: from django.shortcuts import render # Create your views here. from app01 import models def b ...
- 2015-2016 ACM-ICPC Southwestern Europe Regional Contest (SWERC 15)
C. Canvas Painting 合并果子. E. Wooden Signs \(dp(i,l,r)\)表示第\(i\)块木板的长度区间为\([l,r]\)的方案数,根据题意,\(l\)或\(r\ ...
- hdu 2639 Bone Collector II(01背包 第K大价值)
Bone Collector II Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- 第二章FISCO BCOS sdk下载和配置是使用
想了解相关区块链开发,技术提问,请加QQ群:538327407 前提: 1.已经搭建好了一个底层,并且可以正常运行 2.确定外部是否可以连接,如果是云上的服务器,要保证外网可以访问 正式流程 1.下载 ...
- HDU 6623"Minimal Power of Prime"(数学)
传送门 •题意 给你一个大于 1 的正整数 n: 它可以分解成不同的质因子的幂的乘积的形式,问这些质因子的幂中,最小的幂是多少. •题解 定义 $ans$ 表示最终答案: ①如果 $ans \ge 5 ...
- dotnet core 2.1 使用阶梯编译
在 dotnet core 2.1 可以使用阶梯编译的方法,从 dotnet framework 开始,在代码的所有方法在第一次进入的时候就需要使用 JIT 进行编译为本机的代码.可以看到代码是在第一 ...
- java 文件过滤器 java.io.FilenameFilter
File 类里有方法: String[] list(FilenameFilter filter) 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录. File ...
- 新手该如何学习JavaScript ?
JavaScript入门 - 01 准备工作 在正式的学习JavaScript之前,我们先来学习一些小工具,帮助我们更好的学习和理解后面的内容. js代码位置 首先是如何编写JavaScript代码, ...
- win10 uwp 解决 SerialDevice.FromIdAsync 返回空
调用 SerialDevice.FromIdAsync 可能返回空,因为没有设置 package.appmanifest 可以使用端口 打开 package.appmanifest 文件添加下面代码 ...
- linux进程一个阻塞 I/O 的例子
最后, 我们看一个实现了阻塞 I/O 的真实驱动方法的例子. 这个例子来自 scullpipe 驱 动; 它是 scull 的一个特殊形式, 实现了一个象管道的设备. 在驱动中, 一个阻塞在读调用上的 ...