一、聊一聊网络数据传输
一般我们在做文件上传的时候,都会使用流进行操作,代码就不贴了。这个方法很常见。下面我们将从微观的方面去描述这个上传的过程,微观的过程很多人应该不是很了解。
上面的过程大概解析如下:
- jvm向os发出read系统调用,发生上下文切换,从用户态切换成内核态
- 从外部存储读取文件内容,通过直接内存映射的方式,将文件内容存入内核空间的缓冲区
- 将数据从内核缓冲区拷贝到用户空间缓冲区,read系统调用返回,从内核态切换成用户态
- jvm向os发出write系统调用,发生上下文切换,从用户态切换成内核态
- 将数据从用户缓冲区拷贝到socket缓冲区
- 数据最终经过socket通过DMA传动到硬件缓冲区,write系统调用返回,从内核态切换成用户态
上面你的整个过程发生了4次拷贝,上下文切换发生了4次。
二、零拷贝
看完了上面的数据传输的过程,我们在看下零拷贝的微观过程,还是通过图来说明。
和上面的图比较,少了上面步骤的3、5。不在将数据拷贝到用户缓冲区,也没有发生cpu拷贝。
三、在NIO中的运用
NIO对零拷贝的支持,我们可以使用FileChannel类中的transferTo()方法。