磁盘I/O工作机制:访问文件

在Java中,读 & 写对应了 read() & write() 两个系统调用,但只要系统调用,就会存在内核空间地址用户空间地址切换的问题(操作系统为了保护系统安全,必须将内存空间和用户空间进行隔离),因为数据可能需要从内核空间用户空间复制。

如果遇到了非常耗时的操作,如磁盘I/O,数据得从磁盘–>内核空间–>用户空间,复制了两遍,将会非常缓慢。

因此操作系统在内核空间加入了缓存机制,也就是说:如果用户程序访问的是同一段磁盘地址的数据,将会从上一次在内核空间的缓存中直接取得,这样就只复制了一次。

接下来会介绍几种访问文件的方式:

  1. 标准访问文件方式

    • 当调用read()接口时,操作系统检查在内核的高速缓存中有没有数据,如果有就直接返回;否则从磁盘中读取,然后再缓存在内核中。

    • 当调用write()接口时,数据从用户地址空间–>内核地址空间的缓存中,操作完成。

      至于什么时候写到磁盘,由操作系统决定,除非调用sync同步,强制写入磁盘中。

    用户地址空间内核地址空间物理磁盘

    应用缓存1
    应用缓存2
    高速页缓存1
    高速页缓存2
    磁盘数据
    read方法
    write方法

  2. 直接I/O方式

    • 程序直接访问磁盘数据,不经过操作系统内核,这样做能够减少一次数据复制。
    • y优点:适用与由程序实现~~(而不是操作系统)~~的数据库管理系统等,因为操作系统不知道应该缓存哪些数据、失效哪些数据,但是程序知道。
    • 缺点:如果访问的数据不在缓存中,那么每次都会直接从磁盘加载,而这种加载相对非常慢,多次之后会变得十分低效。
    用户地址空间内核地址空间物理磁盘

    应用缓存1
    应用缓存2
    高速页缓存1
    高速页缓存2
    磁盘数据
    read方法
    write方法

  3. 同步访问文件方式

    • 数据的读&写都是同步操作,和标准访问不同的是:只有当数据被成功写到磁盘时,才返回标志给应用程序
    • 性能差,只针对于数据安全性要求高的场景,通常由硬件完成
    用户地址空间内核地址空间物理磁盘

    应用缓存1
    应用缓存2
    高速页缓存1
    高速页缓存2
    磁盘数据
    read方法
    write方法

  4. 异步访问文件方式

    • 当访问数据的线程发出请求后,线程会接着处理其他事情,而不是阻塞(等待),只有当数据返回时才继续处理后续操作。
    • 能提高程序效率,但不是访问文件的效率
    用户地址空间内核地址空间物理磁盘

    应用缓存1
    应用缓存2
    高速页缓存1
    高速页缓存2
    磁盘数据
    read方法
    write方法

  5. 内存映射方式

    • 将操作系统内存中的某块区域和磁盘中的文件夹关联,访问内存时转化为访问磁盘文件的某段数据(和直接IO的区别就是这个映射,相当于一个定位,就快的多)
    • 目的是减少数据的复制操作,此时这两个空间的数据都相当于是共享的
    用户地址空间内核地址空间物理磁盘

    地址映射
    地址映射
    应用缓存1
    应用缓存2
    高速页缓存1
    高速页缓存2
    磁盘数据
    read方法
    write方法

Java序列化&反序列化

​ Java序列化就是将一个对象转化为一串二进制的字节数组,然后通过保存这个字节数组进行持久化。而且达到持久化的目的,必须实现java.io.Serializable接口。

​ Java反序列化就是将字节数组再重新构造成对象。

序例化对象

要序例化一个对象,分如下步骤:

  • 创建某种OutputStream对象,然后将其封装在一个ObjectOutputStream对象内
  • 调用writeObject()即可将对象序列化(对象序列化基于字节,因此使用InputStream和OutputStream继承类层次结构)。

反序列化和序列化过程正好相反,需要将一个InputStream封装在ObjectInputStream内,然后调用readObject()获取一个引用,它指向一个向上转型的Object,所以必须向下转型才能直接设置它们。

对于序列化对象的代码:

public class Serialize implements Serializable {public int num = 1;public long id = 777;public static void main(String[] args) throws IOException {//初始化FileOutputStream fos = new FileOutputStream("filepath");ObjectOutputStream oos = new ObjectOutputStream(fos);//开始干事情Serialize sl = new Serialize();//我自己写的对象oos.writeObject(Serialize);oos.flush();oos.close();}
}

另外,在纯Java环境下,Java序列化能够很好地工作;但是在多语言环境下,会出问题,尽量还是用JSON或XML这些通用的数据结构。

网络I/O工作机制

基础知识

首先你得懂TCP的三次握手和四次挥手,在《计算机网络》中有详细说明,不做过多解释。

要想加速网络的I/O,首先要分析一下影响网络的因素

  • 网络带宽:1s内能传输的最大比特数,平均网络带宽为1.7Mb/s
  • 传输距离:也就是数据要在光纤中走的距离,因为有一个折射率,所以大概只有光速的2/3,比如杭州和青岛的两台机子进行同步操作必定会有一个30ms的延时
  • TCP拥塞控制:详细见《计算机网络》

Java Socket工作机制

Socket 是描述计算机之间完成相互通信一种抽象功能。下面将通过一组比喻&一张图让你了解Socket的工作机制:

  • 两台主机=两个城市
  • 物理链路=高速通道
  • Socket=交通工具
  • 要交付的数据=要运输的货物
  • 通信协议=交通工具的相关规则(比如说电动车不准上高速[狗头])

大致过程:

主机1的程序A和主机2的程序B通信
通过Socket建立连接
底层TCP/IP协议来建立TCP连接
底层IP协议来寻址网络中的主机

但是一台主机上可能运行着多个应用程序,所以,就要通过 TCP 或 UDP 的地址也就是端口号来指定,端口号又对应一个Socket。这样就可以通过一个 Socket 实例,唯一代表一条通信链路了。下面将具体介绍是如何建立链路的。

建立通信链路

当客户端要与服务端通信:

在客户端

  • 客户端首先要创建一个 Socket 实例,操作系统将为这个 Socket 分配一个端口号(port)
  • 创建一个套接字数据结构,包含本地和远程地址&端口号(这个数据结构将一直保存在系统中直到这个连接关闭)
  • 进行 TCP 的三次握手协议
  • Socket 实例的构造函数正确返回,Socket 实例对象就宣布正式创建完成,否则将抛出 IOException 错误。

在服务端

  • 服务端将创建一个 ServerSocket 实例(比较简单,只要端口号未占用,一般实例创建都会成功)

  • 操作系统也会为 ServerSocket 实例创建一个底层数据结构,包含指定监听的端口号和包含监听地址的通配符(通常情况下都是“*”即监听所有地址)

  • 调用 accept() 方法时,进入阻塞状态,等待客户端的请求。


  • 当一个新的请求到来时,将为这个连接创建一个新的套接字数据结构(包含请求源地址和端口)。

  • 这个数据结构,将会关联到 ServerSocket 实例的一个未完成的连接“数据结构“列表中(注意这时服务端与之对应的 Socket 实例并没有正式创建完成,待三次握手完成后,就会将这个 Socket 实例对应的数据结构从未完成列表中移到已完成列表中)

    所以 ServerSocket 所关联的列表中每个数据结构,都代表与一个客户端的建立的 TCP 连接(无论是否完成)

数据传输

传输数据是我们建立连接的主要目的,如何通过 Socket 传输数据,下面将详细介绍。

  • 当连接已经建立成功,服务端和客户端都会拥有一个 Socket 实例,两边的 Socket 实例都有一个 InputStreamOutputStream,正是通过这两个对象来交换数据。

  • Socket 对象正式创建完毕时,操作系统将会为 InputStreamOutputStream 分别分配一定大小的缓冲区,以便数据的写入和读取

  • 写入端将数据写到 OutputStream 对应的 SendQ 队列中,当队列填满时,数据就将会一起发送,到读取端的InputStreamRecvQ 队列中。(如果这时 RecvQ 已经满了,那么 OutputStreamwrite 方法将会阻塞直到 RecvQ 队列有足够的空间容纳 SendQ 发送的数据)

注意:

  • 这个缓存区的大小&写入端的速度&读取端的速度,非常影响该连接的数据传输效率,所以在写入和读取还要有一个协调的过程
  • 如果两边同时传送数据时可能会产生死锁,在后面 NIO 部分将介绍避免这种情况。

2.2磁盘IO网络IO工作机制相关推荐

  1. Linux命令进阶-cpu监控内存监控文件IO网络IO性能分析

    Linux命令进阶-cpu监控内存监控文件IO网络IO性能分析 前言 1 linux基础命令 1.1 grep 1.2 ls 1.3 find 1.4 ulimit 1.5 curl 1.6 scp ...

  2. 实战:如何对磁盘和网络IO进行评估、监控、定位和优化?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 后台回复"k8s",可领取k8s资料 生产中经常遇到一 ...

  3. 深入分析 Java I/O 的工作机制--转载

    Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道.在当今这个数据大爆炸时代, ...

  4. JavaWeb技术内幕二:Java IO工作机制

    IO问题是当今web应用所面临的主要问题之一,因为数据在网络中随处流动,在这个流动过程中都涉及IO问题,并且大部分应用的瓶颈都是IO瓶颈. 本章将从IO的角度出发,介绍IO类库的基本架构,磁盘IO的工 ...

  5. 详解磁盘IO、网络IO、零拷贝IO、BIO、NIO、AIO、IO多路复用(select、poll、epoll)

    文章很长,但是很用心! 文章目录 1. 什么是I/O 2. 磁盘IO 3. 网络IO 4. IO中断与DMA 5. 零拷贝IO 6. BIO 7. NIO 8. IO多路复用 8.1 select 8 ...

  6. 网络模型——四种常见网络IO模型

    文章目录 1.IO读写原理 1.1 内核缓冲区和进程缓存区 1.1.1 用户进程和操作系统 1.1.2 缓冲区的目的 1.2 Java读写IO底层流程 2.四种主要的IO模型 2.1 基本概念 2.1 ...

  7. 后端开发【一大波有用知识】网络通信模型和网络IO管理

    简单的C/S通信模型(accept阻塞的话,就只能一个客户端接进来) socket()函数 //函数原型.返回:若是成功则为非负数,如出错则为 -1 int socket(int domin, int ...

  8. 深入分析 Java I/O 的工作机制

    深入分析 Java I/O 的工作机制 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道.在当今这个数据大爆炸时代 ...

  9. 分布式计算 MapReduce与yarn工作机制

    一.第一代hadoop组成与结构 第一代Hadoop,由分布式存储系统HDFS和分布式计算框架MapReduce组成,其中,HDFS由一个NameNode和多个DataNode组成,MapReduce ...

  10. 深入了解Java I/O的工作机制

    Java I/O操作类 在i/o类中有将近80个类,大致分为四组 1.基于字节操作的I/O接口:InputStream和OutStream 2.基于字符操作的I/O接口:Writer和Reader 3 ...

最新文章

  1. 基于Android5.0的Camera Framework源码分析 (三)
  2. js json对象转字符串_Mock.js模拟数据实现前端独立开发
  3. IEnumerableT和IQueryableT区分
  4. 1092 最好吃的月饼 (20 分
  5. Java加密与解密的艺术~数字证书~模型分析
  6. 统计数字字符和空格 (15 分)
  7. Bootstrap3 带表格的面板
  8. html5晋级之路-学习笔记表单
  9. 7.28-说说对javaweb的感想吧
  10. postman下载安装汉化及使用
  11. PROE 安装提示注册号丢失
  12. 生化危机4重生 java_生化危机-绝密报告4
  13. pixel 刷入自己编译的Android 8.0 安装Xposed 显示 Verified Boot (dm-verity) prevents the device from booting
  14. ARIMA模型的拖尾截尾问题
  15. 武汉新时标文化传媒有限公司短视频的类型
  16. 如何通过组策略统一为公司电脑设置“兼容性视图设置”
  17. 计算机标记的定义,标记网格法
  18. GA001-181-14
  19. Illustrator “图像裁切”功能如何使用?
  20. ADS1.2+2440+j-link(亲测)

热门文章

  1. iPhone查询商品历史价格详细教程
  2. python教程cos_Python爬虫入门教程 12-100 半次元COS图爬取
  3. 计算机操作系统(2)
  4. 服务器sni协议,关于 https 的 SNI(Sever Name Indication) 问题记录
  5. 知识体系结构---备份
  6. 工资,一般讲税前还是税后?
  7. 《霍乱时期的爱情》摘要
  8. centos:/usr/bin/perl is needed by mysql-community-server
  9. linux中为什么要分区,为什么要分区
  10. HUSTOJ超级详细部署文档