java基础_IO底层原理

java I/O 系统

对于程序设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务。I/O系统设计的困难之处在于:

1、I/O系统的接收端往往有很多(文件、控制台、网络链接等)。

2、I/O类库一般也需要兼容不同的处理方式(按字符、按行、按字)。

JAVA I/O类库的设计其实是相当的复杂,涉及到了很多的类。所以导致很多的初学者手足无措,不知道该使用那些库去处理IO。在这边博文中我们来了解一下JAVA I/O的底层原理.

I/O底层原理往往隐藏在JAVA编程知识之下,是开发人员必须掌握的基本原理。可以说是基础中的基础。

I/O读写基本原理

我们尝试从操作系统的底层原理入手,来说明I/O读写的底层原理。

在Linux操作系统中,为了保护内核的安全,操作系统将内存划分为内核空间、用户空间;内核模块运行在内核空间,用户程序运行在用户空间。内核模块有权限访问所有的系统资源,而用户程序只能访问用户空间(用户程序是没有权限访问硬件设备的);

用户程序需要访问硬件设备,则只能通过系统调用。如用户程序需要进行网络I/O的读写,则需要进行write、read系统调用,具体调用流程如下:

在这里插入图片描述

1、网卡设备将用户发送的数据保存到内核缓冲区。

2、操作系统会对内核缓冲区进行监控,等待缓冲区达到一定大小的时候,再进行I/O设备的中断处理,将数据复制到用户缓冲区。这一步由操作系统完成,用户是无感知的。

3、用户程序从用户缓冲区读取数据,处理完成后,将响应信息写入用户缓冲区,并通过write系统调用将用户缓冲区的数据写入内核缓冲区。

4、操作系统监控内核缓冲区,将内核缓冲区的数据通过网卡发送给client。

至此,一次I/O调用处理完成,需要注意的是,一个操作系统中,内核缓冲区只有一个,用户缓存区则存在很多个(一个用户进程,一个用户缓冲区)。

思考:为什么要设计缓存。

1、计算机的外部物理设备与内存、CPU相比,有着非常大的差距。

2、外部物理设备的读写涉及系统中断,发生系统中断的时候,需要保存之前进程的数据和状态等信息。中断结束的时候,还需要恢复之前进程的数据和状态。相当耗费系统资源。

四种主要的I/O模型

同步: 可以简单理解为由用户进程主动询问内核进程I/O读写是否已经完毕。因为I/O调用的发起和I/O准备完毕之后的询问,都是由用户进程主导,所以我们称为同步。

异步: I/0准备完毕后,内核进程主动通知用户进程I/O准备完毕。很明显,I/O系统调用的发起和I/O准备完毕之后的通知,是由不同的进程主导的,所以称为异步。

阻塞: 发起I/O系统调用之后,用户进程一直等待系统调用完成,而不去处理其他任务。

非阻塞: 发起 I/O系统调用之后,用户进程不用一直等待系统调用完成。可以处理一些其他的任务。

同步阻塞I/0

这里以读为例进行说明,同步阻塞I/O的整个调用流程如下。

1、用户进程发起 read 系统调用。

2、用户进程一直等待 I/O 准备完成。

3、用户进程接触阻塞状态,重新运行起来。

同步阻塞I/O的缺点是:每个连接配备一个独立的线程,一个线程维护一个I/O连接,系统调用的时候,线程切换的开销会非常的巨大,性能很低,基本上是不可用的。

linux 系统下,socket 连接默认是阻塞模式。

同步非阻塞I/O

这里以读为例进行说明,同步非阻塞I/O的整个调用流程如下。

在这里插入图片描述

1、用户进程发起 read 系统调用,系统调用会立刻返回,哪怕I/O没有准备完成。

2、用户进程处理一些其它的事情。

3、用户进程再次询问I/O调用是否准备完成。

4、…

和阻塞同步I/O的唯一区别在于,用户进行需要不断去询问内核进程I/O是否准备完毕。

因为不断地轮询,这将会占用大量的CPU时间,所以 同步非阻塞I/O 的效率也是非常的地下,在生产环境中,一般也很少使用。

I/O多路复用

为了解决同步非阻塞I/O中不断轮询的问题。于是就有了 “I/O” 多路复用。目前支持I/O多路复用的系统调用有 select、epoll; 几乎所有的操作系统都支持select 系统调用; epoll是在Linux2.6内核中引入的,是select的增强版。

I/O多路复用的原理是(Linux操作系统):在Linux操作系统中,每个socket连接,会被抽象成一个 IO文件描述符,通过 select/epoll 系统调用,可以监控到多个 IO文件描述符是否处于就绪状态,如果是就绪状态,则返回给用户进程。

JAVA中的NIO 就是采用的这种方式,使用方式如下:

1、将read文件描述符(socket),注册到Linux的 select、epoll 选择器中。

2、通过Linux select/epoll 轮询处于就绪状态的socket连接。

3、用户进程获取到就绪状态的列表之后,处理数据。

我们可以将I/O多路复用看做是 同步非阻塞I/O 的升级版本

异步I/O

这里以读为例进行说明,异步I/O的整个调用流程如下。

1、用户进程发起 read 系统调用,系统调用会立刻返回。并且注册回调方法。

2、I/O准备完成后,内核进程调用注册的回调方法。

很明显异步I/O需要维护很多的回调方法,而且其变成的难度是比较高的。目前Linux操作系统对它的支持并不完善。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值