首页 > 其他分享 >传统的IO存在什么问题?为什么引入零拷贝的?

传统的IO存在什么问题?为什么引入零拷贝的?

时间:2022-11-01 16:36:47浏览次数:43  
标签:缓冲区 内核 IO 引入 拷贝 拷贝到 数据 切换


传统的IO存在什么问题?为什么引入零拷贝的?

如果服务端要提供文件传输的功能,我们能想到的最简单的方式是:将磁盘上的文件读取出来,然后通过网络协议发送给客户端。

传统 I/O 的工作方式是,数据读取和写入是从用户空间到内核空间来回复制,而内核空间的数据是通过操作系统层面的 I/O 接口从磁盘读取或写入。

代码通常如下,一般会需要两个系统调用:


read(file, tmp_buf, len); write(socket, tmp_buf, len);


代码很简单,虽然就两行代码,但是这里面发生了不少的事情。

传统的IO存在什么问题?为什么引入零拷贝的?_运维

首先,期间共发生了 4 次用户态与内核态的上下文切换,因为发生了两次系统调用,一次是 read() ,一次是 write(),每次系统调用都得先从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态。

上下文切换到成本并不小,一次切换需要耗时几十纳秒到几微秒,虽然时间看上去很短,但是在高并发的场景下,这类时间容易被累积和放大,从而影响系统的性能。

其次,还发生了 4 次数据拷贝,其中两次是 DMA 的拷贝,另外两次则是通过 CPU 拷贝的,下面说一下这个过程:

  • 第一次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区里,这个拷贝的过程是通过 DMA 搬运的。
  • 第二次拷贝,把内核缓冲区的数据拷贝到用户的缓冲区里,于是我们应用程序就可以使用这部分数据了,这个拷贝到过程是由 CPU 完成的。
  • 第三次拷贝,把刚才拷贝到用户的缓冲区里的数据,再拷贝到内核的 socket 的缓冲区里,这个过程依然还是由 CPU 搬运的。
  • 第四次拷贝,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程又是由 DMA 搬运的。

我们回过头看这个文件传输的过程,我们只是搬运一份数据,结果却搬运了 4 次,过多的数据拷贝无疑会消耗 CPU 资源,大大降低了系统性能。

这种简单又传统的文件传输方式,存在冗余的上文切换和数据拷贝,在高并发系统里是非常糟糕的,多了很多不必要的开销,会严重影响系统性能。

所以,要想提高文件传输的性能,就需要减少「用户态与内核态的上下文切换」和「内存拷贝」的次数

标签:缓冲区,内核,IO,引入,拷贝,拷贝到,数据,切换
From: https://blog.51cto.com/sourcebyte/5814234

相关文章

  • Istio workloadEntry实例
    服务说明在网格外部运行有nginx服务,有两个实例Nginx2001:监听地址为172.29.1.201:8091,Nginx版本为1.20Nginx2002:监听地址为172.29.1.202:8091,Nginx版本为1.20N......
  • AIRIOT物联网低代码平台如何配置OPC DA驱动?
    AIRIOT物联网低代码平台提供了丰富的驱动,兼容了市面上95%以上的传感器、控制器及数据采集设备等,并且在持续增加中,能够快速、便捷地实现数据采集与控制功能。AIRIOT物联......
  • playwright提示:Navigation failed because page crashed!
    背景今天运行playwright官网的实例,尽然报错了。上周相同的用例还是可以执行的啊提示信息如下:Navigationfailedbecausepagecrashed!解决办法关闭全部谷歌浏览器,然......
  • 406.queue-reconstruction-by-height 根据身高重建队列
    问题描述406.根据身高重建队列解题思路首先根据身高对数组重新排序,再根据ki进行插入操作。排序时,需要对排序的比较方法重写,参见C++sort排序函数用法。同时,考虑到基于......
  • POM 引入本地jar
    <dependency><groupId>SVSClient</groupId><artifactId>SVSClient</artifactId><version>2.8</version><scope>system</scope><systemPath>${pr......
  • @Transactional和try-catch一起使用造成事务回滚失效
    同时使用@Transactional和try-catch,发现执行以下代码事务会失效,数据还是进行了修改操作1@Override2@Transactional(rollbackFor=Exception.class)3pub......
  • 更改Android Studio默认ConstraintLayout布局
    看到网上很多人说改安装路径下的simple.xml.ftl里面的内容即可,可自己4.2.1版本并不存在AndroidStudio\plugins\android\lib\templates\activities\common\root\res\layou......
  • Istio ServiceEntry实例
    服务说明在网格外部运行有nginx服务,有两个实例Nginx2001:监听地址为172.29.1.201:8091,Nginx版本为1.20Nginx2002:监听地址为172.29.1.202:8091,Nginx版本为1.20N......
  • [转]Docker启动Get Permission Denied
    经测试RHEL7.6下,加完用户组后,需重启docker原文地址:Docker启动GetPermissionDenied-warm3snow-博客园(cnblogs.com)以下问题及解决方法都在Ubuntu16.04下,其他环......
  • C++:51---继承中的构造函数、析构函数、拷贝控制一系列规则
    一、继承中的构造函数根据构造函数的执行流程我们知道:派生类定义时,先执行基类的构造函数,再执行派生类的构造函数拷贝构造函数与上面是相同的原理二、继承中的析构函数根据析......