磁盘IO工作机制

磁盘IO工作机制

ref: 《深入分析java web 技术内幕》 by:许令波

几种访问文件的方式

文件读取和写入的 IO 操作都是调用操作系统提供的接口,因为磁盘设备是由操作系统管理的,应用程序要访问物理设备,只能通过系统调用的方式来工作。读和写分别对应 read()/write() 两个系统调用。而只要是系统调用就可能存在内核空间地址到用户空间地址的切换的问题。这是操作系统为了保护系统本身的运行安全,而将内核程序运行使用的内存空间和用户程序使用的内存空间进行隔离造成的。但是这样虽然保证了内核程序的安全,但是也必然存在着数据可能从内核空间向用户空间赋值的问题。

如果遇到非常耗时的操作,如磁盘IO,数据从磁盘复制到内核空间,再从内核空间复制到用户空间,这个过程将会非常缓慢。这是操作系统为了加速 IO 操作,在内核空间使用了缓存机制。也就是将从磁盘读取的文件按照一定的组织方式进行缓存,如果用户程序访问的是同一段磁盘地址的空间数据,那么操作系统将从内核缓存中直接取出返回给用户程序,这样可以减小 IO 的响应时间。

  • 标准访问文件的方式

标准访问文件的方式就是当应用程序调用 read 接口时,操作系统检查在内核的高速缓存中有没有需要的数据,如果已经缓存了,那么就直接从缓存中返回,如果没有,就从磁盘中获取,然后缓存在操作系统的缓存中。

写入的方式是,应用程序调用 write 接口将数据从用户地址空间赋值到内核地址空间的缓存中。这时对用户程序来说写操作就已经完成,至于操作系统什么时候写到磁盘中由操作系统决定,除非显式的调用了 sync 同步命令。

  • 直接 IO 的方式

所谓的直接 IO 的方式就是应用程序直接操作磁盘数据,而不经过操作系统内核数据缓冲区,这样做的目的是为了减小一次从内核缓冲区到用户缓存的数据复制。
这种访问文件的方式通常是在对数据的缓存管理由应用程序实现的数据库管理系统中。
如在数据库管理系统中,系统明确的知道应该缓存哪些数据,应该失效哪些数据,还可以对热点数据进行预加载,提前将数据加载到内存中,可以加速数据的访问效率。
如果这时由操作系统来进行缓存,则很难做到,因为操作不知道哪些是热点数据,哪些数据只会访问一次。操作系统知识简单的缓存最近一次从磁盘读取的数据。
但是直接操作 IO 也有负面影响,如果访问的数据不在应用程序缓存中,那么每次数据都会直接从磁盘加载,这种直接加载会非常的缓慢。通常直接 IO 与 异步 IO 结合使用,会得到比较好的性能。

  • 同步访问文件的方式

同步访问文件的方式比较好理解,就是数据的读取和写入都是同步操作,与标准访问方式不同是:只有数据真正被写入到磁盘中之后,才会返回给应用程序成功的标志。
这种访问文件的方式性能比较差,只有在一些对数据安全性要求较高的场景中才会使用,而且这种操作方式的硬件都是定制的。

  • 异步访问文件的方式

异步访问文件的方式就是当访问数据的线程发出请求之后,线程会接着去处理其他事情,而不是阻塞等待,当请求的数据返回后继续处理下面的操作。
这种访问文件的方式可以明显的提高应用程序的效率,但是不会改变访问文件的效率。

  • 内存映射的方式

内存映射的方式是指操作系统将内存中的某一块区域和磁盘中的文件关联起来,当要访问内存中的一段数据时,转换为访问文件的某一段数据。这种方式的目的同样是减少数据从内核空间缓存到用户空间缓存的数据复制操作,因为这两个空间是共享的。

java 访问磁盘文件

下面介绍一下将数据持久化到物理磁盘的方式。
我们知道数据在磁盘中的最小描述就是文件,也就是说上层应用程序只能通过文件来操作磁盘上的数据,文件也是操作系统和磁盘驱动器交互的最小单元。值得注意的是,在 java 中通常的 File 并不代表一个真实存在的文件对象,当你指定一个路径描述符时,他就会返回代表这个路径的虚拟对象,它可能是一个真实存在的文件或者一个包含多个文件的文件夹。为什么要这样设计呢?因为多数情况下,我们并不关心这是文件是否存在,我们只关心这个文件到底如何操作。那么什么时候会检查这个文件是否真实存在呢?
只有在真正需要读取文件的时候,才会去检查这个文件是否存在
例如:FileInputStream 类是操作一个文件的接口,注意到在创建一个 FileInputStream 对象时会创建一个 FileDescritor 对象,其实这个对象就是真正代表一个存在的文件对象的描述。当我们在操作一个文件对象 时,可以通过 getFD() 方法来获取真正操作的与底层操作系统相关联的文件描述。例如,可以通过 FileDescriptor.sync() 方法将操作系统缓存中的数据强制刷新到物理磁盘中。


当传入一个文件路径时,将会根据这个路径创建一个 File 对象来标识这个文件,然后根据这个 File 对象创建真正读取文件的操作对象,这时将会真正创建一个关联真实存在的磁盘文件的文件描述符 FileDescriptor,这个这个对象可以操作磁盘文件。
由于我们需要的是字符格式,所以需要 StreamDecoder 类将 byte 解码为 char 格式。至于如何从磁盘上读取一段数据,操作系统会帮我们完成。而操作系统如何将数据持久化到磁盘以及如何创建数据结构的,需要根据操作系统使用何种文件系统来回答。

java 序列化技术

Java 序列化是将一个对象转化成一串二进制表示的字节数组,通过保存或转移这些字节数据来达到持久化的目的。需要序列化,对象必须继承 java.io.Serializable 接口。反序列化则是相反的过程,将这个字节数组再重新构造成对象,反序列化必须有原始类作为模板,才能将这个对象还原。
那么序列化后的信息包含哪些信息呢?来实际看下吧

public class Serialize implements Serializable{

    private static final long serialVersionUID = -1687280615424697762L;

    public int num = 1390;

    public static void main(String... args) {
        try {
            FileOutputStream fos = new FileOutputStream("/Users/serialize.dat");
            try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
                Serialize serialize = new Serialize();
                oos.writeObject(serialize);
                oos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出如下:

aced 0005 7372 0015 636f 6d2e 6c69 616e
6a69 612e 5365 7269 616c 697a 65e8 9593
3849 355a 5e02 0001 4900 036e 756d 7870
0000 056e 

分为5部分(具体哪一段代表什么信息,还需要具体看):

  • 第一部分是序列化文件头
  • 第二部分是序列化的类描述
  • 第三部分是对象中各个属性项的描述
  • 第四部分输出该对象的父类信息描述
  • 第五部分输出对象的属性项的实际值

虽然 java 的序列化能保证对象状态的持久保存,但是遇到一些对象结构复杂的情况还是比较难处理的,下面是一些总结:

  • 当父类继承了 Serializable 接口时,子类都可以被序列化
  • 子类实现了 Serializable 接口,父类没有,则父类中的属性不能被序列化(不报错,数据丢失),但是子类属性可以正确序列化
  • 如果序列化属性是对象,则这个对象也必须可以被序列化,否则报错
  • 在反序列化是,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错
  • 在反序列化是,如果 serialVersionUID 被修改,则反序列化会失败。(如果不显示声明,则会在编译时自动生成,但字段有修改后,自动生成的不一致,会导致失败,最好显式指定)

在纯java环境下,java 序列化能够很好的工作,但是在多语言的环境下,用java 序列化存储后,很难用其他语言还原出结果。在这种情况下,还是尽量存储通用的数据结构,如 JSON 或者 XML 数据结构。

原文地址:https://www.cnblogs.com/paxing/p/10641818.html

时间: 2024-08-07 21:46:03

磁盘IO工作机制的相关文章

Java IO工作机制分析

Java的IO类都在java.io包下,这些类大致可分为以下4种: 基于字节操作的 I/O 接口:InputStream 和 OutputStream 基于字符操作的 I/O 接口:Writer 和 Reader 基于磁盘操作的 I/O 接口:File 基于网络操作的 I/O 接口:Socket 1 IO类库的基本结构 1.1 基于字节操作的IO接口 基于字节操作的IO接口分别是InputStream和OutputStream,InputStream的类结构图如下所示: 同InputStream

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

I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的瓶颈都是 I/O 瓶颈.本文的目的正是分析 I/O 的内在工作机制,你将了解到:Java 的 I/O 类库的基本架构:磁盘 I/O 工作机制:网络 I/O 的工作机制:其中以网络 I/O 为重点介绍 Java Socket 的工作方式:你还将了解到 NIO 的工作方式,还有同步和异步以及阻塞与非阻塞的区别,最

深入分析 Java I/O 的工作机制(转载)

声明:本文转自 http://www.ibm.com/developerworks/cn/java/j-lo-javaio/ I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的瓶颈都是 I/O 瓶颈.本文的目的正是分析 I/O 的内在工作机制,你将了解到:Java 的 I/O 类库的基本架构:磁盘 I/O 工作机制:网络 I/O 的工作机制:其中以网络 I/

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

Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道.在当今这个数据大爆炸时代,I/O 问题尤其突出,很容易成为一个性能瓶颈.正因如此,所以 Java 在 I/O 上也一直在做持续的优化,如从 1.4 开始引入了 NIO,提升了 I/O 的性能.关于 NIO 我们将在后面详细介绍. Java 的 I/O 操作类在包 java.io 下,大概有将近 80 个类,但是这些类大概可以

rsync工作机制(翻译)

本篇为rsync官方推荐文章How Rsync Works的翻译,主要内容是Rsync术语说明和简单版的rsync工作原理.本篇没有通篇都进行翻译,前言直接跳过了,但为了文章的完整性,前言部分的原文还是保留了. How Rsync WorksA Practical Overview Foreword The original Rsync technical report and Andrew Tridgell's Phd thesis (pdf) Are both excellent docum

MapReduce工作机制详解

1.MapTask工作机制整个Map阶段流程大体如上图所示.简单概述:input File通过split被逻辑切分为多个split文件,通过Record按行读取内容给map(用户自己实现的)进行处理,数据被map处理结束之后交给OutputCollector收集器,对其结果key进行分区(默认使用hash分区),然后写入buffer,每个map task都有一个内存缓冲区,存储着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式存放到磁盘,当整个map task结束后再对

通过blktrace, debugfs分析磁盘IO

前几天微博上有同学问我磁盘util达到了100%时程序性能下降的问题,由于信息实在有限,我也没有办法帮太大的忙,这篇blog只是想给他列一下在磁盘util很高的时候如何通过blktrace+debugfs找到发生IO的文件,然后再结合自己的应用程序,分析出这些IO到底是谁产生的,最终目的当然是尽量减少不必要的IO干扰,提高程序的性能. blktrace是Jens Axobe写的一个跟踪IO请求的工具,linux系统发起的IO请求都可以通过blktrace捕获并分析,关于这个工具的介绍请自行Goo

【好书摘要】性能优化中CPU、内存、磁盘IO、网络性能的依赖

系统优化是一项复杂.繁琐.长期的工作,优化前需要监测.采集.测试.评估,优化后也需要测试.采集.评估.监测,而且是一个长期和持续的过程,不 是说现在优化了,测试了,以后就可以一劳永逸了,也不是说书本上的优化就适合眼下正在运行的系统,不同的系统.不同的硬件.不同的应用优化的重点也不同. 优化的方法也不同.优化的参数也不同.性能监测是系统优化过程中重要的一环,如果没有监测.不清楚性能瓶颈在哪里,怎么优化呢?所以找到性能 瓶颈是性能监测的目的,也是系统优化的关键.系统由若干子系统构成,通常修改一个子系

详细深入分析 ClassLoader 工作机制

申明:本文首发于 详细深入分析 Java ClassLoader 工作机制 ,如有转载,注明原出处即可,谢谢配合. 详细深入分析 Java ClassLoader 工作机制 什么是 ClassLoader ClassLoader 作用 1ClassLoader 类结构分析 2ClassLoader 的等级加载机制 Java默认提供的三个ClassLoader ClassLoader加载类的原理 原理介绍 2为什么要使用双亲委托这种模型呢 3 但是JVM在搜索类的时候又是如何判定两个class是相