文章目录

  • 前言
  • 一、基本概念
    • 1.1、用户空间和内核空间
    • 1.2、操作系统的IO
    • 1.3、java的IO流
    • 1.4、IO流的分类
    • 1.5、扩展
      • 1.5.1、同步与异步
      • 1.5.2、阻塞与非阻塞
      • 1.5.2、组合模式
  • 二、五种IO模型
    • 2.1、同步阻塞IO- BIO
    • 2.2、同步非阻塞IO- NIO
    • 2.3、多路复用IO(异步阻塞IO)
      • 2.3.1、基于select/poll
      • 2.3.2、基于epoll
      • 2.3.3、对比
    • 2.4、信号驱动IO- SIGIO
    • 2.5、异步非阻塞IO- AIO
  • 总结

前言

Java对数据的操作是通过流的方式,学好IO流可以方便地实现数据的输入/输出操作,其重要性不言而喻。


以下是本篇文章的思维导图


一、基本概念

1.1、用户空间和内核空间

为了保护操作系统的安全,会将内存分为内核空间和用户空间。用户进程想要操作数据,必须通过系统调用(System Call)向内核(Kernel)发出指令,将数据从内核空间复制到用户空间,才能操作数据。

1.2、操作系统的IO

以Linux操作系统为例,Linux是一个将所有的外部设备视为文件来操作的的系统。那么我们对外部设备的操作可看作是对文件的操作,由于LINUX中进程无法直接操作I/O设备,其必须通过系统调用,请求内核(kernel)来协助完成I/O动作, 内核会为每个I/O设备维护一个缓冲区。

对于一个输入操作来说,用户进程在系统调用后,内核会先看缓冲区中有没有相应的缓存数据,没有的话再到设备中读取,因为设备IO一般速度较慢,需要等待;内核缓冲区有数据则直接复制到进程空间。

一个完整的IO分为两个阶段:

  1. 读取 设备空间(网络、磁盘等)的数据 内核空间的缓冲区
  2. 复制 内核空间的缓冲区的数据 用户进程空间

1.3、java的IO流

java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操作。

在java中,把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为“流”(stream)。通过流的形式,允许java程序使用相同的方式来访问不同的输入/输出源。流是一种有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两个设备间的传输成为流,流的本质是数据传输

IO按存储形式分为内存IO、网络IO和磁盘IO三种,我们通常所说的IO指的是后两者,网络IO就是通过网络进行数据的拉去和输出。磁盘IO主要是对磁盘进行读写工作。

1.4、IO流的分类

● 按流方向:输入流、输出流;
● 按数据类型:字节流(8位字节)、字符流(16位字节)。

字符流和字节流的区别:

  1. 字节流本身没有缓冲区,字符流本身带有缓冲区,所以缓冲字节流相比缓冲字符流,效率提升非常明显
  2. 字节流可以处理一切文件,而字符流只能处理纯文本文件。

以下是常见流的分类表:


1.5、扩展

1.5.1、同步与异步

同步和异步关注的是调用方和被调用方的交互,本质是通讯机制。

同步:调用方发起调用后,等待或者轮询的去查看被调用方是否就绪
异步:调用方发起调用后,便开始做自己的事情,当被调用方完成时,会得到IO 完成的通知

1.5.2、阻塞与非阻塞

阻塞和非阻塞关注的是调用者在等待调用结果时的状态,本质是描述当前线程状态。

阻塞:调用方发起调用后,一直等待,线程会被挂起(不能去做其他事情)
非阻塞:调用方发起调用后,会立即收到一个状态值,该线程去做其他事情。

1.5.2、组合模式


同步异步是相对于客户端来说,而阻塞非阻塞是相对于服务端来说。因此,异步可以提升客户端的体验,非阻塞可以避免服务端创建新的线程(或进程),减少了CPU资源的消耗。


二、五种IO模型

因为IO分为两个阶段,期间都需要等待和数据的复制,这大大的限制了IO的执行效率,如何才能解决这个性能瓶颈呢?

1、降低IO中等待的比重
2、避免数据的复制

为了解决IO效率,提出了五种IO模型


2.1、同步阻塞IO- BIO

用户进程调用内核进程后,需要等待内核IO彻底操作完,才能返回用户空间。如下图:

  1. 用户进程发起recvfrom后,进入阻塞状态

  2. 内核进程收到recvfrom后,就开始准备数据,等待数据到达内核缓冲区

  3. 内核进程收到完整数据后,就会将数据从内核缓冲区复制到用户空间的内存,然后返回结果(如:复制数据字节数)

  4. 用户进程收到内核返回结果后,才解除阻塞状态,继续运行。

recvfrom: linu系统调用函数。

优点:

开发简单,用户态进程阻塞时,不会占用CPU资源

缺点:

在高并发场景下,需要大量的线程来维护大量的网络连接,内存和线程切换开销大,性能低。


2.2、同步非阻塞IO- NIO

用户进程调用内核进程后,不用等内核IO操作彻底完成,即可执行后续的指令。如下图:

  1. 用户进程发起recvfrom后,内核进程没有准备好数据,直接返回EWOULDBLOCK错误

  2. 用户进程会执行其他任务,期间用户进程会不断发起recvfrom,如果收到错误说明还没准备好

  3. 内核进程收到完整数据后,用户进程发起recvfrom后会被阻塞,直到数据从内核缓冲区复制到用户空间

  4. 用户进程收到内核返回结果后,才开始处理接收到的数据。

优点:

用户态进程调用内核态进程后,不需要阻塞,实时性好

缺点:

用户态进程需要不断轮询内核态进程,大量占用CPU资源,浪费CPU资源。假如1000个线程,单位时间内会有1000次系统调用去轮询执行结果。
轮询时间不好控制
轮询需要程序员实现循环读取文件描述符,代码编写复杂


2.3、多路复用IO(异步阻塞IO)

2.3.1、基于select/poll

Select是内核提供的系统调用,支持一次查询多个系统调用的可用状态,当任意一个结果状态为可用时就返回,用户进程再次发起一次系统调用进行数据读取。

在多路复用IO模型中,多个进程的IO可以注册到一个复用器(select)上,然后会有一个线程不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。

  1. 用户进程调用内核select,将发起recvfrom的socket连接注册到Linux的select/poll选择器中,内核开启轮询流程。

  2. 内核空间内,遍历所有的文件描述符, 将准备好数据的socket连接加入到就绪列表。

  3. 用户进程轮询选择器上注册的就绪socket列表有值时,用户进程发起recvfrom并阻塞,复制数据到用户缓冲区。

  4. 用户进程复制完后,内核返回结果,用户进程解除阻塞状态,开始处理用户空间的数据,继续执行后续指令。

优点:

一个选择器线程,可以同时处理大量网络请求,不必创建大量线程,减轻了系统开销

缺点:

select底层采用数组实现,存在连接数限制,因此poll应运而生,其底层采用链表实现,解决了连接数限制
select与poll解决了NIO重复无效系统调用问题,却引来新的问题:

  1. 用户空间和内核空间之间,文件描述符集合拷贝
  2. 内核循环遍历文件描述符集合,浪费CPU时间

select/poll 虽然减少了用户进程发起的系统调度,但内核工作量只增不减,内核存在无效的循环遍历


2.3.2、基于epoll

通过事件驱动,减少select/poll引入的内循环遍历,如下图:

epoll相较于select/poll,多了两次系统调用,其中epoll_create 建立与内核的连接,epoll_ctl注册事件,epoll_wait阻塞用户进程,等待IO事件。

  1. 用户进程调用内核epoll_create,创建一个eventpoll对象,再通过内核epoll_ctl,将需要监听的socket放入eventPoll对象的rbr(红黑树)中,同时会给内核中断处理程序注册一个回调函数。(如果这个句柄处理程序中断到了,会把它放入rdlist(就绪链表)里)

  2. socket接收到数据,会对CPU发起硬中断,内核执行回调函数,把socket的数据写入rdlist(就绪链表)里,当执行内核epoll_await时,立即返回准备就绪链表里的数据。

  3. 用户进程取链表中fd做实际的read/write操作

优点:

一个选择器线程,可以同时处理大量网络请求,不必创建大量线程,减轻了系统开销
通过共享空间,避免了数据的来回拷贝

缺点:

epoll,提升了IO执行效率,但是IO执行的第一阶段,数据准备阶段还是处于阻塞状态。


2.3.3、对比

2.4、信号驱动IO- SIGIO

信号驱动IO,在数据的准备阶段不会阻塞用户进程,内核将数据准备好后,发送SIGIO信号通知用户进程进行IO操作。

  1. 用户进程发起sigaction系统调用,内核进程立即返回,用户进程继续执行

  2. 内核进程准备好数据后,会发给用户进程一个SIGIO信号

  3. 用户进程收到信号后,会发起recvfrom系统调用

  4. 用户进程进入阻塞状态,并复制数据到用户空间缓冲区,复制完后,处理接收到的数据

优点:

数据准备阶段,不会阻塞用户进程
Netty支持NIO,开发简单实用

缺点:

IO执行第二阶段【复制数据到用户空间缓冲区】时,用户进程被阻塞


2.5、异步非阻塞IO- AIO

异步IO真正的实现了IO全流程非阻塞,即用户进程(线程)在等待数据报和数据报从内核拷贝到用户空间这两阶段都是非阻塞的。其流程如下图:

  1. 用户进程发起sigaction系统调用后,内核进程立即返回一个状态值,用户进程去做其他事情。

  2. 内核进程把接收的数据复制到用户空间后,再去通知用户进程

  3. 用户进程接收到通知后,直接去处理用户空间接收的数据。

类似java的回调模式,用户进程向内核空间注册了各种IO事件的回调函数,由内核主动调用

优点:

完全异步

缺点:

Linux对AIO性能不比NIO有优势,实现并不成熟


总结

以上就是今天要讲的内容,本文从操作系统进行文件读写入手,对同步、异步、阻塞、非阻塞以及它们组合而成的IO模式进行了介绍,还介绍了Linux操作系统中的五种IO模型,相信大家应该有了一定的了解。如有不恰当的地方,还请雅正。

参考资料:
1.要问技术多NB,请问IO模型知多少?
2.Java IO流详解
3.Java中五中IO模型详解

文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览 95856 人正在系统学习中


http://www.taodudu.cc/news/show-6187186.html

相关文章:

  • 面试官:请讲一讲IO流核心模块与基本原理是什么?
  • SSL安全连接是什么意思?HTTPS安全登录指的什么?
  • Security安全登录
  • JWT安全登录
  • Web登录安全详解
  • 账号与安全
  • 用户登录安全问题
  • 【微信小程序】shiro安全登录界面实现
  • springboot-security安全登录
  • 登陆的安全考虑
  • [OS-Linux] CentOS 7.x 安全登录策略设置
  • 使用 PHP 和 MySQL 的安全登录系统
  • 使用腾讯企业邮箱为什么强烈建议启用安全登录?怎么启用?
  • MySQL安全登录策略
  • Shell脚本导出导入MySQL建表语句
  • Web性能压力测试工具-Webbench
  • 1 网站压力测试工具 WEB性能测试 Web Bench
  • 【WEB】Web性能压力测试工具
  • web压力測试-Web Bench
  • 十个免费的Web负载/压力测试工具
  • 网页压力测试工具
  • 网站压力测试工具was
  • Web必备性能压力测试工具WebBench与ApcheBench(ab)详解
  • 自动控制原理-频率特性 G(jw ) 定义
  • 频率调制
  • 自动控制原理笔记-频率响应法-频率特性的概念
  • 基于单片机的频率测量控制系统设计 (频率计)(电路+程序)
  • Linux CPU频率控制
  • 基于FPGA的DDS直接数字频率合成器,频率和相位控制字可配置,在vivado2019.2平台中verilog开发.含testbench
  • 「自控原理」5.1 频率特性及其图示

IO流的详解,彻底了解IO流相关推荐

  1. 【Linux】基础IO(万字详解) —— 系统文件IO | 文件描述符fd | 重定向原理

  2. IO多路复用机制详解

    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking IO):默认创建的s ...

  3. Nginx源码研究之nginx限流模块详解

    这篇文章主要介绍了Nginx源码研究之nginx限流模块详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 高并发系统有三把利器:缓存.降级和限流: 限流的目的是通过对并 ...

  4. java8 stream运行原理之并行流原理详解

    上一篇文章<java8 stream运行原理之顺序流原理详解>介绍了顺序流的执行原理,本文接着上一篇介绍并行流的执行原理. 一.如何创建并行流 调用parallel()方法可以创建并行流, ...

  5. 网站流量日志系统知识详解----【点击流事件详解】

    网站流量日志数据分析系统知识详解 1. 点击流数据模型 1.1 点击流概念 点击流(Click Stream)是指用户在网站上持续访问的轨迹.可以通过对网站日志的分析可以获得用户的点击流数据. 1.2 ...

  6. Java IO流使用详解

    1.前言 在众多流行的编程语言中,Java对IO的处理应该是最特殊的,Java打着"尽量减少IO类的设计理念",搞出了目前应该是最复杂的一套IO相关类,并称之为Java流. 对于新 ...

  7. 【Java基础】· IO流习题详解

    写在前面 Hello大家好, 我是[麟-小白],一位软件工程专业的学生,喜好计算机知识.希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!! ...

  8. Java之IO流技术详解

    何为IO? 首先,我们看看百度给出的解释. I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分. i是写入,Input的首字母.o是输出,Output的首字母. IO 也称为 ...

  9. Java SE 第八十八,八十九,九十讲 递归深度剖析 IO流深入详解,递归作业详解

    1.所谓递归(Recursion),就是方法调用自身,对于递归来说,一定有一个出口,让递归结束,只有这样才能保证不出现死循环. 2.作业:给定任意一个目录,以树形方式展现该目录中所有子目录和文件.另外 ...

最新文章

  1. 2、ESXI安装出错
  2. 时间戳的转换和星期转换
  3. python简单体育竞技模拟_Python程序设计思维练习---体育竞技分析-阿里云开发者社区...
  4. IntelliJ IDEA中文乱码解决办法
  5. Java 并发编程之 volatile
  6. redhad安装git
  7. 用python计算工程量_基于Python脚本程序的电缆工程量快速统计方法与流程
  8. 敏感词高效检测从浅到深
  9. 学会这120个PS小技巧,工作效率提高5倍!
  10. 【计算机系统结构】~ ROM/PROM/EPROM/E2PROM/FLASH、SOC 片上系统、总线、CPU 处理器、Cache、DDR、ARM 体系结构、虚拟内存、内核 kernel
  11. 怎么把cad做的图分享给别人_怎么将CAD图转换
  12. iText7 学习笔记2--页眉页脚
  13. XML详解----Schema
  14. 技术分享| 探索视频感知编码
  15. OSChina 周日乱弹 ——我2018年的目标是什么?
  16. 编写ringBuff过程中遇到的一次bug
  17. ADO Execute 方法 (ADO Connection)
  18. nginx服务器网站目录浏览,Nginx开启目录浏览功能 | 系统运维
  19. 并行算法笔记(一)——性能测评
  20. 查看redis当中缓存的内容的命令

热门文章

  1. MySQL查询分析器EXPLAIN或DESC用法
  2. 交叉熵损失函数详解推导
  3. Facebook名人软件Mentions有了Android版本
  4. 单链表的头插法与尾插法
  5. linux添加失败的原因,linux下execvp失败设置errno=7的原因是什么?
  6. 1.ShowWindow
  7. Vih和ViL和Vhys
  8. NLP基础知识点:ROUGE
  9. ROUGE评价算法学习
  10. 鸿蒙系统脱离了安卓么,曝华为手机将脱离安卓系统,3月上线新系统全面改为鸿蒙内核!...