为了对比出零拷贝技术的优越性,这里使用直接IO技术,内存映射文件技术,零拷贝技术进行对比
直接IO技术
上图中,内核缓冲区是 Linux 系统的 Page Cahe。为了加快磁盘的 IO,Linux 系统会把磁盘上的数据以 Page 为单位缓存在操作系统的内存里,这里的 Page 是 Linux 系统定义的一个逻辑概念,一个 Page 一般为 4K。
可以看出,整个过程有四次数据拷贝,读进来两次,写回去又两次:磁盘-->内核缓冲区-->Socket 缓冲区-->网络。
直接 IO 过程使用的 Linux 系统 API 为:
ssize_t read(int filedes, void *buf, size_t nbytes);
ssize_t write(int filedes, void *buf, size_t nbytes);
内存映射文件技术
可以看出,整个过程有三次数据拷贝,不再经过应用程序内存,直接在内核空间中从内核缓冲区拷贝到 Socket 缓冲区。
内存映射文件过程使用的 Linux 系统 API 为:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
零拷贝技术
使用零拷贝技术,连内核缓冲区到 Socket 缓冲区的拷贝也省略了,如下图所示:
内核缓冲区到 Socket 缓冲区之间并没有做数据的拷贝,只是一个地址的映射。底层的网卡驱动程序要读取数据并发送到网络上的时候,看似读取的是 Socket 的缓冲区中的数据,其实直接读的是内核缓冲区中的数据。
零拷贝中所谓的“零”指的是内存中数据拷贝的次数为 0。
零拷贝过程使用的 Linux 系统 API 为:
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
在JDK中,提供的:
FileChannel.transderTo(long position, long count, WritableByteChannel target);