图片取材自图灵课堂!
在早期计算机中,系统的I/O流程如下:
1. CPU通过系统和I/O总线给磁盘控制器发出指令。
1. 磁盘控制器收到指令后,控制器负责读取磁盘数据,将磁盘数据放入控制器内部缓冲,然后在I/O总线上发出一个CPU中断信号。
1. CPU收到中断信号,将磁盘控制器的缓冲区按字节依次读取到CPU寄存器中,然后将寄存器数据写入内存,此期间CPU不会调度进程做额外的计算工作。
由于整个数据的传输过程都需要CPU亲自参与,如果数据量很大的时候,显然这种模式会消耗 大量CPU时间,于是直接内存访问DMA技术就诞生了。
DMA是一种特殊的芯片,它可以控制设备控制器和内存数据交互,无需CPU干预控制和拷贝过程。
1. CPU通过设置DMA控制器的寄存器,告诉DMA需要传送数据的地址等信息。
1. DMA将I/O请求发送给磁盘控制器。
1. 磁盘控制器收到DMA的I/O请求,将磁盘数据拷贝到磁盘控制器的内部缓冲区,缓冲区到达一定量会给DMA发起一个中断信号。
1. DMA收到磁盘控制器的信号,将磁盘控制器内部缓冲区数据根据I/O总线拷贝到操作系统内核空间。
1. DMA读取了足够多的数据就会给CPU发送中断信号。
1. CPU收到DMA完成一次传输的信号,将内核空间的数据拷贝到指定进程用户空间地址
零拷贝
技术并不是一次拷贝也没有,而是减少文件的拷贝次数。
mmap
:内存文件映射,操作系统可以通过mmap()函数将磁盘上的文件映射到内存的一块区域,进程可以像读写内存一样来读写该文件。在传统的read()函数中,read函数会将内核缓冲区数据拷贝到用户空间中,mmap函数无需这一次拷贝。mmap()函数会把内核缓冲区数据映射到进程的用户态空间中。
在Linux2.1版本中,系统提供了一个函数sendfile(),ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
,它可以代替read和write两个系统调用,这样相比于mmap就会又减少一次系统调用,也减少了2此进程的上下文切换,全流程只需要2次上下文切换和3此数据拷贝。
在Linux2.4版本后,并且网卡支持SG-DMA技术的情况下,sendfile()函数还可以进一步优化,更加少一步数据拷贝
在I/O系统中,数据从设备控制器拷贝到操作系统内核缓冲区,这个内核缓冲区就是PageCache。它的作用是将操作系统最近频繁读写的数据写入PageCache中提高性能,因为磁盘I/O的速度不高,参考局部性原理,PageCache有着预读的功能。但是,在传输大文件的时候PageCache会被很快写满,其它热点数据就无法更好利用PageCache,从总体上降低了操作系统的效率。所以针对大文件的传输,不建议使用PageCache而是建议绕过设备控制器缓存拷贝到PageCache的这一个流程,这个流程叫直接I/O或者叫异步I/O。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- niushuan.com 版权所有 赣ICP备2024042780号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务