IO的原理及Java中的各种IO模型


一、内存与io

当我们去读写磁盘的数据时会发生磁盘IO,这里从Java的角度出发看一下底层内核发生了哪些操作:
1.发生一次Read/Write的IO操作会伴随一次System call (系统中断 int x 80 内核级指令),告诉OS我需要中断当前系统正在处理的事,马上进行IO操作。这里有三种分配方式:
Allocate 堆内分配,在Java虚拟机的堆内分配
AllocateDirect 堆外分配 直接分配,在堆外虚拟机内分配
MMap 用户态和内核态共享的一块区域,且这个区域是PageCache的映射,由于MMap共享两个区域且不会产生系统调用也是就是不会发生int 80 中断 ,所以它比其他的两种方式要快
性能对比:Allocate < AllocateDirect <MMap
2.进入内核态PageCache管理,PageCache的大小为4kb用来存储用户态写写进来的数据,考虑:为什么使用PageCache来存储,且大小为4k?
PageCache可以较少系统IO的调用,每个PageCache相当于是一个高速缓存区,提升读取速度,优化内存。只要PageCache的状态变为Dirty后会被写入磁盘,但PageCache不会全量分配,不可控,会产生缺页的问题。至于大小为4K我认为道理和磁盘的扇区大小原理一样。

在这里插入图片描述

二、Java的BIO,NIO,多路复用IO

首先介绍之前我们先来了解一下“同步”,“异步”,“阻塞”,“非阻塞”概念。
用最通俗的话来讲:
“同步阻塞”指需要程序自己调用进行获取,且调用方法的时候回产生阻塞,直到有返回值才可以继续下一步。
“同步非阻塞”指同样需要程序自己进行调用获取,但是调用后不会产生阻塞,方法会立即给出返回值,你自己得去判断什么时候去处理。
“异步阻塞” 没有这个概念,异步和阻塞是互相矛盾的
“异步非阻塞” 目前Linux系统内核没有提供通用的异步模型,Window的有.

1.BIO

优势:编码简单,适用于一个或者多个线程模型下的业务场景使用
劣势:accpect和R/W会产生Blocking阻塞,每个客户端连接会创建一个线程(c10k问题?)。CPU频繁切换线程,每次会触发一次系统调用从用户态切换到内核态,资源消耗巨大

2.NIO

优势:非阻塞,可以使用一个线程同时管理不同的客户端的Accpect和R/W,减少线程的资源消耗
劣势:效率慢,同时管理多哥连接时需要循坏判断当前连接的是否发生读写,有一定的延时。同样每次会触发一次系统调用从用户态切换到内核态,资源消耗巨大

3.多路复用型IO

多路复用分为三种,分别是select,poll 和epoll
1.select
每次创建的fds个数有限制,就是每次读取的文件描述符有大小限制
2.poll
没有fds(1024)的限制,功能基本和select一样,每次都需要轮询
3.epoll
epoll不传递fds,规避遍历,在内核中维护一个红黑树放入一些fd(文件描述符),伴随内核基于中断处理完fd的buffer,把有状态的fd放入链表调用epoll_wait(=seletor)对fd进行R/W

NIO,SELECT,POLL都需要遍历所有的IO,询问IO的状态,只不过NIO遍历的成本在用户态和内核态的切换上。SELECT,POLL一次系统调用,将fds(文件描述符)传给内核,内核去遍历fds,修改状态。
SELECT,POLL的弊端:
1.每次都需要重新和重复传递fds
2.每次内核被调用触发一次全量的fds的遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值