I/O流(包括操作系统与内核,用户空间),I/O工作原理,Java I/O流的设计及Java IO系统


在介绍IO流之前,先介绍一下一些基础的概念

一.操作系统与内核

1.1操作系统

  1. 俗话说,操作系统是连接系统软硬件的一座桥梁,它自身本质上就是一个软件。
  2. 他的作用就是管理计算机硬件与软件资源的学习通软件。

1.2内核

  • 内核主要是操作系统的核心软件,负责管理系统的进程、内存、设备驱动软件、文件和网络系统等等,为应用程序提供对计算机硬件的安全访问服务。

1.3 关系图

在这里插入图片描述

二、内核空间和用户空间

2.1:目的:

  • 为了避免用户进程直接操作内核,保证内核安全,操作系统将内存寻址空间划分为两部分:

2.2、内核空间(Kernel-space):

  • 在Linux中,Linux驱动程序一般工作在内核空间,但也可以工作在用户空间;
  • Linux简化了分段机制,使得虚拟地址与线性地址总线是一致的,因此,Linux的虚拟地址空间也为0~4G。Linux内核将这4G字节的空间分为两部分,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用成为内核空间。而将较低的3G字节(从0x00000000到0xBFFFFFFF),供各个进程使用,称为用户空间。
  • 因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内所有进程共享,于是,从具体进程角度来看,每个进程可以拥有4G字节的虚拟空间。
  • 内核空间中存放的是内核代码和数据,而进程的使用空间中存放的是用户程序的代码和数据,不管是内核空间还是用户空间,他们都处于虚拟空间中,虽然内核空间占据了每个虚拟内存中最高1GB字节,但映射到物理内存却总是从最低地址(0x00000000)开始。
  • 对内核空间来说,期地址映射事件单的线性映射,0xc0000000就是物理地址和线性地址之间的的位移量,在Linux代码中就叫做PAGE_OFFSET

2.3、用户空间(User-space):

  • 用户空间就是用户进程所在的内存区域,而用户进程和系统进程的所有数据都在内存中,
  • 供用户进程使用,只能访问受限权限,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,只能才能访问这些特殊权限。
  • 为了安全,内核空间和用户空间是隔离的,即使用户空间的程序崩溃了,内核也不受影响。
  • 处于用户态的程序只能访问用户空间,而处于内核态的程序可以访问用户空间和内核空间。

2.4、内核空间与用户空间通讯

  • 内核空间和用户空间一般通过系统调用进行通信。

2.5、用户态和内核态的区别

  • 当一个任务(进程)执行系统调用而陷入内核代码执行时,我们就称进程处于内核运行态即内核态。此时处理器处于特权级最高的0级内核中执行;当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈,当进程在执行自己的内核代码时,则称其处于用户运行态即用户态,此时处理器在特权级最低的3级用户代码中运行。
  • 内核态与用户态时操作系统的两种运行级别,Intel x86架构提供Ring0-Ring3四种级别的运行模式,Ring0级别最高,Ring3级别最低。
  • Linux使用了Ring三级别运行用户态,Ring0作为内核态,没有使用Ring1和ring2 .Ring3状态不能访问Ring0的地址空间,包括代码和数据。程序特权级别的不同,所具有的权利也不同

2.6、用户态转换为内核态的3种方式

  • 这三种方式是系统在运行时由用户态转到内核态的最主要的方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

2.6.1、系统调用

  • 这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务进程完成工作,比如fork()实际上就是执行一个创建新进程的一种系统调用,而系统调用的及至的核心还是使用了操作系统为用户特别开方的一个中断来实现。

2.6.2、异常

  • 当CPU再执行运行在用户态下的程序时,阿生了某些事先不可预知的异常,这时会触发有当前运行切换到处理此异常的内核相关程序中,也就转到了内核态。

2.6.3、外围设备的中断

  • 当外围设备完成用户其去年高俅的操作后,会向CPU发出相应的中断信号,,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果事先执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的转换,

2.7、系统调用:

  • 是操作系统的最小功能单位,通过提供一些基本功能的接口供应用程序调用来调度内核空间管理的资源。当程序运行从用户态到内核态,那么处在用户态的进程需要先保存当前的数据以及运行的指令,方便回到用户态时继续执行,这中间还有很多其他的事情需要做,例如CPU寄存器需要保护和加载,系统调用器的二代吗需要执行等。

在这里插入图片描述

三、数据流

  • 计算机中的数据是基于随着时间变换高低电压信号传输的,这些数据信号连续不断,有着固定的传输方向,类似水管中水的流动,因此抽象数据流I/O流的概念:指义序有顺序的,有起点和终点的字节集合。
  • 抽象出数据流的作用:实现程序逻辑与底层硬件解耦,通过引入数据流作为程序与硬件设备之间的抽象层,面向通用的数据输出接口编程,而不是具体硬件特性,程序和底层硬件可以独立灵活替换和扩展。
  • System,IO.Stream类是所有流的抽象基类,Stream类及其派生类提供这些不同类型的输入和输出的一般视图,使程序员不必了解操作系统和基础设备的具体细节。
  • 根据基础数据源和储存库,流可能只支持这些功能中的一部分,用户可以通过使用CanRead、CanWrite和Canseek属性,可实现应用程序查询流的功能。
  • Read和Write方法读写各种不同格式的数据。对于支持查找的流,使用Seek和Setlength方法以及Position和Length属性可以查询和修改流的当前位置和长度。
  • 有些流用于实际执行基础数据的本地缓冲以提高性能,对于这样的流,Flush方法可以用于清除所有内部缓冲区并确保将所有的数据写入基础数据源或存储库。
  • 在Stream上调用Close将刷新所有缓冲区处理的数据,本质上使用用户调用Flush方法。Close也会释放操作系统资源,如文件句柄、网络连接或用于任何内部缓冲的内存,BufferedStream类提供了建一个讲过缓冲区的流环绕另一个流功能,一遍提高读写功能。
  • 如果需要不带后背存储区(即位存储桶)的流,应使用NULL。

四、IO工作原理

4.1、磁盘IO

典型的IO读写磁盘工作原理如下;

在这里插入图片描述

4.2、COU复制

  • 在DMA技术出现之前,应用程序与磁盘之间的I/O操作都是CPU的中断完成的,每次用户进程读取磁盘数据时,都需要CPU中断将数据读进暂存器,然后发起I/O请求等待 数据读取和拷贝完成,然后写进其他地方,每次的I/O中断都导致CPU的上下文切换。

4.3、DMA复制

  • DMA(Direct Memory Access,直接存储器访问),基于DMA访问方式,系统主内存与硬件设备的数据传输可以省去CPU的全程调度,
  • 具体流程:CPU对DMA控制器初始化,向I/O接口发出操作指令,I/O接口提出DMA请求DMA控制器对DMA请求判断优先级即评比,向总线裁决逻辑提出总线要求,当CPU执行完当前总线周期即可释放总线控制权,此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。
    • 值得注意的是:
      • 读写操作基于系统调用实现
      • 读写操作经过用户缓冲区,内核缓冲区,应用过程并不能直接操作磁盘
      • 应用进程读取操作时需阻塞直到读取到数据

4.4、网络I/O

  • 值得注意的是:
    • 网络I/O读写操作经过用户缓冲区,Socket缓冲区
    • 服务端线程在从调用开始到它返回有数据报准备好这段时间是阻塞的,read返回成功后,线程开始处理数据报

五、Java I/O流设计

5.1、流介绍

  • java中所有的数据都是使用流读写的,流是一组有顺序,有方向,有起点和重点的字节集合,是对数据传输的总称

5.2、流体系

请添加图片描述

5.3、流的实现类

请添加图片描述

5.4、java中流的划分

  • 按照方向划分
    • 输入流:从各种输入设备(磁盘、网卡、键盘……)将数据读取到当前程序中
    • 输出流:从当前程序将数据写入输出设备(磁盘、网卡、屏幕……)
  • 按照数据传输单元划分:
    • 字节流:一字节为单位的数据传输流,InputStream和OutputStream
    • 字符流:以字符为单位的数据传输流,Reader、Writer
  • 按照功能划分
    • 节点流:用于直接操作目标设备的流
    • 过滤流(高级流):对一个已经存在的流进行包装,以提供更强大灵活地读写功能。

5.5、java I/O原理

在这里插入图片描述

六、Java I/O系统

6.1、Java标准类库中各种各样的类以及它们的用法

6.1.1 File类

  • File(文件)这个类实际上既能代表一个特定文件的名称,又能代表一个目录下的一组文件的名称;
  • 如果它指的是一个文件集,我们就可以对这个类调用list()方法,这个方法会返回一个字符数组,因为元素的个数是固定的,所以我们想取得不同的目录列表,只需要再创建一个不同的File对象就可以了
import java.io.File;

import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;

public class DirList {
   
    public static void main(String[] args) {
   
        File path=new File(".");
        String[] list;
        if (args.length==0){
   
            list=path.list();
        }else {
   
            list =path.list(new DirFilter(args[0]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在炮火中前进

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值