内核概述与NIO

内核,是一个操作系统的核心。是基于硬件的第一层软件扩充,提供操作系统的最基本的功能,是操作系统工作的基础,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。


我们开发的程序全是基于内核之上,所有计算机的资源调用都要经过内核的。内核作为一软件,他对内存资源也是有需求的。

下图是内核对内存的划分

System   代码运行所需要的空间
pageCache 页缓存 根据功能的不同可进一步划分
      SwapCache 虚拟内存页转换缓存(linux swap)
      Mapped 文件映射 (FileChannel.map方式打开文件占用mapped)
      Nio  file.   利用nio的文件所需要的Cache (FileChannel.transferTo和 FileChannel.transferFrom)
      Io buffer   利用传统io文件所需要的Cache
Buffer  用做数据缓冲区。
          JAVA 中也可以用 ByteBuffer.allocateDirector申请分配的Buffer

总结

      Cache  用于加快程序读取数据缓冲区

      Buffer  不同的设备(模块)之间传输数据的区域

 

Buffer的基本概念

容量 (capacity) : 表示 Buffer 最大数据容量,缓冲区容量不能为负,并且创建后不能更改。 缓冲区其实就是数据组,因为是数组,所以数据容量一旦固定就不能修改了
限制 (limit): 第一个不应该读取或写入的数据的索引,即位于 limit 后的数据不可读写。缓冲区的限制不能为负,并且不能大于其容量。
位置 (position): 下一个要读取或写入的数据的索引。缓冲区的位置不能为负,并且不能大于其限制
标记 (mark)与重置 (reset): 标记是一个索引,通过 Buffer 中的 mark() 方法指定 Buffer 中一个特定的 position,之后可以通过调用 reset() 方法恢复到这个 position。
 
标记、 位置、 限制、 容量遵守以下不变式: 0 <= mark <= position <= limit <= capacity  注意:mark初始化为-1,表示没有标记过   

 

浅谈NIO与零拷贝

传统IO的数据拷贝流程如上左图:

  1. 数据需要从磁盘拷贝到内核空间,再从内核空间拷到用户空间(JVM)。
  2. 程序可能进行数据修改等操作
  3. 再将数据拷贝到内核空间,内核空间再拷贝到网卡内存,通过网络发送出去(或拷贝到磁盘)。

上右图:

  •     传统IO的数据拷贝流程共经历了4次内核态和用户态的切换。

NIO零拷贝的数据拷贝改进的地方如上图:

  • 我们已经将上下文切换次数从4次减少到了2次
  • 将数据拷贝次数从4次减少到了3次(其中只有1次涉及了CPU,另外2次是DMA直接存取)。

如果硬件再进一步支持,可以从Read buffer 直接到 NIC buffer,省去中间2的步骤,实现真正的ZeroCopy.

注:

  • 磁盘到内核空间属于DMA拷贝(DMA即直接内存存取,原理是外部设备不通过CPU而直接与系统内存交换数据)。
  • 内核空间到用户空间则需要CPU的参与进行拷贝,既然需要CPU参与,也就涉及到了内核态和用户态的相互切换

NIO的零拷贝由transferTo()方法实现。transferTo()方法将数据从FileChannel对象传送到可写的字节通道(如Socket Channel等)。在内部实现中,由native方法transferTo0()来实现,它依赖底层操作系统的支持。

使用场景一般是:

  1. 文件较大,读写较慢,追求速度
  2. JVM内存不足,不能加载太大数据
  3. 内存带宽不够,即存在其他程序或线程存在大量的IO操作,导致带宽本来就小

DMA技术升级管道技术

   

  1. 早先这些IO接口都是由CPU独立负责。所以当发生大规模读写请求时,CPU的占用率很高。
  2. 操作系统为了避免CPU完全被各种IO接口调用占用,引入了DMA(直接存储器存储)。当应用程序对操作系统发出一个读写请求时,会由DMA先向CPU申请权限,申请到权限之后,内存地址空间与磁盘之间的IO操作就全由DMA来负责操作。(解放了CPU)
  3. 通道的方式,程序与文件之间建立一个通道用于连接,然后通过缓冲区进行数据存取,通过通道进行连接传递。(解决了IO大量并发的时候,对总线冲突调用,把请求打包起来调用)

    如果硬件支持,NIO采用的是通道技术,解放了CPU,也减少了总线冲突情况

JAVA中Pipe类也提供对管道的支持,通过Linux命令 lsof能查到。

NIO的直接内存

首先,它的作用位置处于传统IO(BIO)与零拷贝之间,为何这么说?

传统IO,可以把磁盘的文件经过内核空间,读到JVM空间,然后进行各种操作,最后再写到磁盘或是发送到网络,效率较慢但支持数据文件操作。
零拷贝则是直接在内核空间完成文件读取并转到磁盘(或发送到网络)。由于它没有读取文件数据到JVM这一环,因此程序无法操作该文件数据,尽管效率很高!
而直接内存则介于两者之间,效率一般且可操作文件数据。

直接内存(mmap技术)将文件直接映射到内核空间的内存,返回一个操作地址(address),它解决了文件数据需要拷贝到JVM才能进行操作的窘境。而是直接在内核空间直接进行操作,省去了内核空间拷贝到用户空间这一步操作。

接缓冲区也存在着一些缺点:

  1. 不安全
  2. 消耗更多,因为它不是在JVM中直接开辟空间。这部分内存的回收只能依赖于垃圾回收机制,垃圾什么时候回收不受我们控制。
  3. 数据写入物理内存缓冲区中,程序就丧失了对这些数据的管理,即什么时候这些数据被最终写入从磁盘只能由操作系统来决定,应用程序无法再干涉。

NIO的直接内存是由MappedByteBuffer实现的。核心即是map()方法,该方法把文件映射到内存中,获得内存地址addr,然后通过这个addr构造MappedByteBuffer类,以暴露各种文件操作API。《JAVA直接内存(堆外内存)
 

直接缓冲区适合与数据长时间存在于内存,大量数据的操作时更加适合
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值