Linux系统I/O操作与零拷贝
1、使用DMA的系统I/O操作要进行4次内核空间与应用程序空间的上下文切换,2次CPU数据拷贝及2次DMA数据拷贝。 Mmap内存映射与标准I/O操作的区别在于当应用程序需要访问数据时,不需要进行内核缓冲区到应用程序缓冲区之间的数据拷贝。
2、简单的说,零拷贝是一种避免CPU将数据从一快存储拷贝到另外一块存储的技术。
3、下面我们通过一个Java非常常见的应用场景:将系统中的文件发送到远端(该流程涉及:磁盘上文件 —— 内存(字节数组) —— 传输给用户/网络)来详细展开传统I/O操作和通过零拷贝来实现的I/O操作。
4、sendfile只适用于将数据从文件拷贝到套接字上,限定了它的使用范围。Linux在17版本引入splice系统调用,用于在两个文件描述符中移动数据。
5、“内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。一个内核不是一套完整的操作系统。Linux中传统的I/O操作是一种缓存I/O,I/O过程中产生的数据传输通常需要在缓冲区中进行多次拷贝。
6、linux系统要把u盘中的文件复制过来需要先把U盘挂载到系统中的某一个位置,然后再使用cp命令完成拷贝。可以参考以下操作步骤:把U盘插入Linux电脑,确保U盘指示灯是亮着的。
零拷贝Zero-copy技术详解
所以异步IO可以做到直接从磁盘缓冲区拷贝到用户缓冲区,适用于大文件传输。
零拷贝(zero-copy)基本思想是:数据报从网络设备到用户程序空间传递的过程中,减少数据拷贝次数,减少系统调用,实现CPU的零参与,彻底消除 CPU在这方面的负载。
Kafka使用零拷贝(Zero-Copy)技术来提供它的性能,所谓的零拷贝是指将数据直接从磁盘文件复制到网卡设备中,而不需要经由应用程序之手,减少了内核和用户模式之间的上下文切换,零拷贝技术通过DMA技术实现。
Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。
可以见到,在这个过程中发生了2次cpu copy和2次DMA copy,以及发生了数次cpu状态切换。 这个操作对于应用服务器来说很频繁,因此带来的开销也是非常大。
我们来重点探究 kafka两个重要过程、以及是如何利用两个零拷贝技术sendfile和mmap的。 传统方式实现: 先接收生产者发来的消息,再落入磁盘。 实际会经过四次copy,如下图的四个箭头。
MMAP和零拷贝
系统调用命令: mmap() 。使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write() 等操作。
在某些情况下,这种零拷贝技术能获得很好的性能。linux下提供类似的系统调用主要有mmap(),sendfile(),splice(). 使用mmap替代read,可以减少CPU拷贝次数。
mmap+write简单来说就是使用 mmap 替换了read+write中的read操作,减少了一次CPU的拷贝。
然后介绍了优化的点分别是减少数据拷贝次数和介绍空间切换次数,于是引出了零拷贝技术: mmap+write、sendfile、sendfile+DMA收集、splice等。最后介绍了内核缓冲区的作用,也引出了异步IO可以处理大文件传输工作。
A: Linux提供了mmap零拷贝来实现我们的需求。 mmap(内存映射)是一个比sendfile昂贵但优于传统I/O的方法。 ① 发出mmap系统调用,导致用户空间到内核空间的上下文切换(第一次上下文切换)。
[转]浅谈Linux下的零拷贝机制
总的来说,带有DMA收集拷贝功能的sendfile实现的I/O只使用了2次用户空间与内核空间的上下文切换,以及2次数据的拷贝,而且这2次的数据拷贝都是非CPU拷贝。
有时候,应用程序在数据传输的过程中不需要对数据进行访问,将数据从linux的页缓存拷贝到用户进程的缓冲区就可以完全避免,传输的数据在页缓冲中就可以处理。在某些情况下,这种零拷贝技术能获得很好的性能。
splice调用利用了Linux提出的管道缓冲区机制, 所以至少一个描述符要为管道。以上几种零拷贝技术都是减少数据在用户空间和内核空间拷贝技术实现的,但是有些时候,数据必须在用户空间和内核空间之间拷贝。