详谈Java I/O 底层原理以及应用

前言

一说到IO,大家都知道write、read,但是在不同操作系统中,IO读写的系统调用的名称可能完全不一样,但是基本功能是一样的。

read系统调用,并不是直接从物理设备把数据读取到内存中。

write系统调用,也不是直接把数据写入到物理设备。

上层应用无论是调用操作系统的rad,还是调用操作系统的write,都会涉及缓冲区。

具体来说,调用操作系统的read,是把数据从内核缓冲区复制到进程缓冲区;而write系统调用,是把数据从进程缓冲区复制到内核缓冲区。

页缓存(page cache)是操作系统为了提升磁盘读写性能在应用进程与磁盘之间加设的提供预读和异步刷盘机制的内核缓冲区

看下图(图引用:https://blog.csdn.net/xiaoduanayu/article/details/107055472?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242

那么缓冲区的目的,是为了减少频繁地与设备之间的物理交换。

java 的 IO 操作是建立在操作系统的 IO 之上的,从最基础的 read/write 系统调用,到具有零拷贝特性的 sendfile、mmap(可看这篇文章:零拷贝sendfile、内存映射mmap原理)。

Page Cache

页缓冲/文件缓冲,通常4K,由若干个磁盘块组成(物理上不一定连续),也即由若干个bufferCache组成

针对文件系统的,是文件的缓存,在文件层面上的数据会缓存到page cache。

Page cache 也叫页缓冲或文件缓冲,是由好几个磁盘块构成,大小通常为4k,在64位系统上为8k,构成的几个磁盘块在物理磁盘上不一定连续,文件的组织单位为一页, 也就是一个page cache大小,文件读取是由外存上不连续的几个磁盘块,到buffer cache,然后组成page cache,然后供给应用程序。

IO模型

同步阻塞IO:

内核IO操作彻底完成后,才会返回用户空间,执行用户操作。在java中socket都是阻塞的。

同步非阻塞IO:

用户空间不需要等待内核IO操作完成后再进行操作,内核立即可以给用户空间返回一个状态,用户空间无需等到内核的IO操作彻底完成,可以立即返回用户空间,执行用户的操作,处于非阻塞的状态。

异步IO:

用户线程通过系统调用,告知内核启动某个IO操作,用户线程返回。内核在整个IO操作(包括数据准备、数据复制)完成后,通知用户程序,用户执行后续的业务操作。

1、当用户线程调用了read系统调用,立刻就可以开始去做其它的事,用户线程不阻塞

2、内核(kernel)就开始了IO的第一个阶段:准备数据。当kernel一直等到数据准备好了,它就会将数据从kernel内核缓冲区,拷贝到用户缓冲区(用户内存)。

3、内核会给用户线程发送一个信号(signal),或者回调用户线程注册的回调接口,告诉用户线程read操作完成了。

优点:无需等待内核操作完成

缺点:需要完成事件的注册与传递,这里边需要底层操作系统提供大量的支持,去做大量的工作

IO多路复用:

目前支持IO多路复用的系统调用,有 select,epoll等等(详情看多路复用之select、poll、epoll)。select系统调用,是目前几乎在所有的操作系统上都有支持,具有良好跨平台特性。

O多路复用模型,建立在操作系统kernel内核能够提供的多路分离系统调用select/epoll基础之上的。多路复用IO需要用到两个系统调用(system call), 一个select/epoll查询调用,一个是IO的读取调用。

和NIO模型相似,多路复用IO需要轮询。负责select/epoll查询调用的线程,需要不断的进行select/epoll轮询,查找出可以进行IO操作的连接。

猜你喜欢

转载自blog.csdn.net/weixin_39082432/article/details/113870553