您的位置:首页 > 汽车 > 新车 > 齐家网和土巴兔哪家好_网页设计地址_推广平台网站有哪些_网络营销策划师

齐家网和土巴兔哪家好_网页设计地址_推广平台网站有哪些_网络营销策划师

2024/10/22 18:26:53 来源:https://blog.csdn.net/qq_40926260/article/details/142836449  浏览:    关键词:齐家网和土巴兔哪家好_网页设计地址_推广平台网站有哪些_网络营销策划师
齐家网和土巴兔哪家好_网页设计地址_推广平台网站有哪些_网络营销策划师

文章目录

  • 用户态和内核态
  • 文件读写原理
  • DMA
  • 零拷贝
    • MMap 机制
    • sendfile() 系统调用

https://en.wikipedia.org/wiki/Zero-copy

零拷贝可以避免中间缓冲区之间的冗余数据拷贝,并减少用户空间和内核空间之间的上下文切换次数。当硬件(磁盘驱动器、网卡、图形卡、声卡)支持DMA(直接内存访问)时,理想的零拷贝(零CPU拷贝)是可能的。

用户态和内核态

用户态和内核态是操作系统中用于管理程序执行权限和资源访问的两种运行模式。它们的设计旨在提供安全性、稳定性和高效性。

  1. 用户态:指程序在执行时的普通运行状态。应用程序在这一状态下运行,不能直接访问硬件资源和内核数据结构。在用户态运行程序的权限受到限制,不能执行可能影响系统稳定性或安全性的操作。
  2. 内核态:内核态是操作系统内核运行的模式,具有完全的访问权限,可以直接与硬件交互。在内核态,操作系统可以执行特权指令,访问内存、设备和系统资源。

用户应用程序运行在操作系统之上,当用户程序需要访问系统资源(比如文件读写等)或执行特权操作时,它必须通过系统调用来请求内核的服务。这会导致上下文切换,从用户态切换到内核态。系统调用会保存用户态程序的状态,切换到内核态执行相应的内核服务,然后再切换回用户态,恢复程序状态。

用户态和内核态的设计是操作系统的核心,确保了系统的安全性、稳定性和高效性。通过这两种模式,操作系统能够有效管理程序的执行,保护系统免受不当操作的影响。

文件读写原理

传统方式文件复制代码如下:

public void copy(String from, String to) throws IOException {byte[] data = new byte[8 * 1024];File fromFile = new File(from);long bytesToCopy = fromFile.length();long bytesCopied = 0;try (FileInputStream fis = new FileInputStream(fromFile);FileOutputStream fos = new FileOutputStream(to)) {while (bytesCopied < bytesToCopy) {int bytesRead = fis.read(data);fos.write(data);bytesCopied += data.length;}fos.flush();}
}

一次复制过程包含一次读和一次写操作

读文件

用户程序通过编程语言提供的读取文件api发起对某个文件读取的请求。此时程序切换到内核态,用户程序处于阻塞状态。由于读取的内容还不在内核缓冲区中,由OS负责发起对磁盘文件的数据读取。读取到数据后,先存放在OS内核的PageCache内存里。然后OS再将数据拷贝一份至用户进程空间的主存ByteBuffer中。此时程序由内核态切换至用户态继续运行程序。程序将ByteBuffer中的内容读取到本地变量中,完成文件数据读取。

在这里插入图片描述

写文件

用户程序通过编程语言提供的写入文件api发起对某个文件写入磁盘的请求。此时程序切换到内核态,用户程序处于阻塞状态,由OS负责发起对磁盘文件的数据写入。用户写入数据后,并不是直接写到磁盘的,而是先写到ByteBuffer中,然后再提交到PageCache中。最后由操作系统决定何时写入磁盘。数据写入PageCache中后,此时程序由内核态切换至用户态继续运行。用户程序将数据写入内核的PageCache缓冲区后,即认为写入成功了。程序由内核态切换回用户态,可以继续后续的工作了。PageCache中的数据最终写入磁盘是由操作系统异步提交至磁盘的。一般是定时或PageCache满了的时候写入。如果用户程序通过调用flush方法强制写入,则操作系统也会服从这个命令。立即将数据写入磁盘然后由内核态切换回用户态继续运行程序。但是这样做会损失性能,但可以确切的知道数据是否已经写入磁盘了。

传统的复制操作需要在用户模式和内核模式之间进行四次上下文切换,在操作完成之前,数据被复制四次。

DMA

DMA 意为 Direct Memory Access,直接内存访问,这种技术能绕过 CPU,直接在内存和外设之间进行数据传输。这样可以减少 CPU 的参与,提高数据传输的效率。

参考:https://www.51cto.com/article/720677.html

传统拷贝方式 CPU 需要阻塞等待磁盘数据读取的中断信号

零拷贝

零拷贝方式文件复制

public void zeroCopy(String from, String to) throws IOException {try (FileChannel source = FileChannel.open(Paths.get(from));FileChannel destination = FileChannel.open(Paths.get(to))) {source.transferTo(0, source.size(), destination);}
}

我们将上下文切换的数量从四个减少到两个,并将数据副本的数量从4个减少到3个(其中只有一个涉及CPU)。但这还没有让我们实现零拷贝的目标。如果底层网络接口卡支持收集操作,我们可以进一步减少内核所做的数据复制。在Linux内核2.4及更高版本中,修改了套接字缓冲区描述符以满足这一要求。这种方法不仅减少了多次上下文切换,还消除了需要CPU参与的重复数据副本。用户端的使用仍然保持不变,但内部函数发生了变化:

MMap 机制

MMap(Memory Map)是 Linux 操作系统中提供的一种将文件映射到进程地址空间的一种机制,通过 MMap 进程可以像访问内存一样访问文件,而无需显式的复制操作。

MMap机制把文件映射到OS内核缓冲区空间,同时共享给用户进程,也可以共享给多个用户进程。映射过程中不会产生实际的数据从磁盘真正调取动作,只有用户程序需要的时候才会调入部分数据。总之也是和普通文件读取一样按需调取。
普通复制操作下,用户程序要读取到磁盘上的数据,要经历4次内核态切换以及4次数据拷贝操作。由于是和用户进程共享内核缓冲区,所以使用了mmap机制要经历4次内核态切换以及3次数据拷贝,少了一次拷贝操作(数据从内核缓冲区到用户进程缓冲区),从而提高了性能。

sendfile() 系统调用

在 Linux 操作系统中 sendFile() 是一个系统调用函数,用于在 Linux 和其他类 Unix 操作系统中高效地将数据从一个文件描述符传输到另一个文件描述符。sendfile 通过在内核空间直接传输数据,避免了用户空间和内核空间之间的多次数据拷贝,从而提高了性能。

使用了 sendfile 的文件复制操作只需要 2 次上下文切换(发起sendfile调用,接收sendfile调用结果)和 2 次拷贝(从磁盘读取到内核空间,从内核空间写到磁盘)


参考:

  1. https://www.cnblogs.com/liuche/p/15455808.html
  2. https://developer.ibm.com/articles/j-zerocopy/
  3. https://www.cnblogs.com/vipstone/p/18237139

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com