我的编程空间,编程开发者的网络收藏夹
学习永远不晚

浅谈Linux的零拷贝技术

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

浅谈Linux的零拷贝技术

前言

在linux系统内部缓存和内存容量都是有限的,更多的数据都是存储在磁盘中。对于Web服务器来说经常需要从磁盘中读取数据到内存,然后再通过网卡传输给用户

img

那么这也算一次I O的过程,都知道IO过程中需要状态的切换还有一系列拷贝过程,都是要时间开销的,那么怎么优化用户态和内核态的状态的切换次数和各种缓冲区之间的拷贝次数,也是linux的服务器实现高并发的重要技术了!

传统数据交互

传统 io 的执行流程: 下面将图左半部分read过程的硬件抽象为磁盘; 图右半部分write过程的硬件设为网卡,模拟webserver进行一次IO的过程; 方便理解;

  • read:将数据从 IO 设备读取到内核缓存区中,再将数据从内核缓冲区拷贝到用户缓冲区
  • write:将数据从用户缓冲区写入到内核缓冲区中,再将数据从内核缓冲区拷贝到 IO 设备

read/write 属于系统调用 syscall,每一次系统调用 ,发生两次上下文切换

  • 调用 syscall 从用户态切换到内核态
  • syscall 返回从内核态切换到用户态

如图所示,传统 io 的过程中,发生了4次空间切换 + 4次拷贝

在这里插入图片描述

不难看出,传统模式下的IO,涉及多次空间切换和数据冗余拷贝,效率并不高。而零拷贝 Zero-Copy 目的就是降低冗余数据拷贝,解放 CPU

  • 减少数据在内核缓冲区和用户缓冲区之间的冗余拷贝(CPU拷贝)
  • 减少系统调用导致的空间切换

目前来看,零拷贝技术的实现手段主要包括:mmap+write、sendfile、sendfile+DMA、splice

零拷贝

首先解释一下,零拷贝中的0,指的是CPU级别的数据拷贝(比如内核缓冲区到用户缓冲区的拷贝,用户缓冲区再到socket缓冲区; 或者内核缓冲区直接到socket缓冲区的拷贝!),并不是DMA硬件的拷贝,否则数据不靠DMA怎么转移呢?

mmap+write

  • 内存映射 memory mapping,mmap 是一种内存映射文件的方法,即将一个文件或者其他对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一映射关系。

mmap可以充当read的功能,将内核读缓冲区地址与用户缓冲区地址进行映射,实现内核缓冲区与用户缓冲区的共享。这样就减少了一次用户态和内核态的CPU拷贝。

mmap + write 流程如图所示,发生了4次切换 + 2次DMA拷贝 + 1次CPU拷贝

在这里插入图片描述

函数原型

#include <sys/mman.h>
// 内存映射
void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);








// 解除映射
int munmap(void *addr, size_t length);

例: 发送方:

// 建立内存映射
char *pMap = (char*) mmap (NULL, fileInfo.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 

send(clientFd, pMap, fileInfo.st_size, 0);

// 解除映射
munmap(pMap, fileInfo.st_size); 

接收方:

// 使用 mmap 前用使用 ftruncate 来扩大文件大小
ftruncate(fd, fileSize);
char *pMap = (char*) mmap (NULL, fileSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

recvCycle(sfd, pMap, fileSize);
munmap(pMap, fileSize);

小结

mmap充当read的功能,进行一次完整的IO,减少了传统方式read数据的时候,从内核态CPU拷贝到用户态的这次拷贝; (发生了4次切换 + 2次DMA拷贝 + 1次CPU拷贝;)

mmap 存在的问题:mmap 对大文件传输有一定优势,但是小文件可能出现碎片,并且在多个进程同时操作文件时可能产生引发 coredump 的 signal。

sendfile

mmap+write 方式有一定改进,但是由系统调用引起的状态切换并没有减少,因此在 Linux 内核2.1版本中引入了 sendfile 系统调用。

sendfile 在两个文件之间通过内核直接传输数据,避免了内核缓冲区和用户缓冲区之间的数据拷贝操作。sendfile 只能用于发送数据,不能用于接收数据。

sendfile 方式只使用一个函数就可以完成之前的 read+write 和 mmap+write 的功能,这样减少一个系统调用(2次状态切换),由于数据不经过用户缓冲区,因此该数据无法被修改。

sendfile 的流程如图所示, 发生了2次切换 + 2次DMA拷贝+1次CPU拷贝

在这里插入图片描述

sendfile + DMA

linux2.4版本后,对 sendfile 系统调用进行优化,配合硬件 DMA,可以直接从内核空间缓冲区中将数据拷贝到网卡,彻底省去了CPU拷贝

如图所示,sendfile + DMA 的过程中发生了2次切换 + 2次DMA拷贝 + 0次CPU拷贝

在这里插入图片描述

sendfile 函数原型

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);



例:

发送方

sendfile(clientFd, fd, 0, fileInfo.st_size);

小结

早期sendfile : 2次切换 (sendfile后,数据不用过用户层了,导致不能修改了,不过也少了两次状态切换!)+ 2次DMA拷贝(磁盘到内核,socket缓冲区到网卡)+ 1次CPU拷贝(内核到socket缓冲区)

改良的sendfile + DMA : 发生了2次切换 + 2次DMA拷贝(磁盘到内核,内核直接到网卡) + 0次CPU拷贝

sendfile 存在的问题:无法对数据进行修改(数据没上到用户层,也没必要,webserver一般都不需要修改,返回的本地的资源!),并且需要硬件层面DMA的支持,并且 sendfile 只能将文件数据拷贝到 socketfd,有一定的局限性。

splice

splice 系统调用在 Linux 2.6 版本引入,不需要硬件支持,并且不再限定于 socket 上,实现了两个普通文件之间的零拷贝

可以在内核缓冲区和 socket 缓冲区间建立管道来传输数据避免了两者之间的 CPU 拷贝操作

在这里插入图片描述

函数原型

#define _GNU_SOURCE 
#include <fcntl.h>

ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);



例:web服务器端代码: transFile.c:

int fds[2];
pipe(fds);

int recvLen = 0;
//当读到的数据量超过文件大小时,即已经读取数据完成
while(recvLen < fileInfo.st_size){
    //将数据从服务器端本地读到管道
    ret = splice(fd, 0, fds[1], 0, 65536, 0);
    //将数据从管道读到客户端
    ret = splice(fds[0], 0, clientFd, 0, ret, 0);
    //计算已经读到的数据量
    recvLen += ret;
}

小结

splice 引入管道机制,实现了普通文件之间的0拷贝,突破了仅限于socket的sendfile0拷贝;

splice 存在的问题:它的两个文件描述符中有一个必须是管道设备

到此这篇关于浅谈Linux的零拷

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

浅谈Linux的零拷贝技术

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

浅谈Linux的零拷贝技术

前言 在linux系统内部缓存和内存容量都是有限的,更多的数据都是存储在磁盘中。对于Web服务器来说,经常需要从磁盘中读取数据到内存,然后再通过网卡传输给用户:那么这也算一次I O的过程,都知道IO过程中需要状态的切换还有一系列拷贝过程,都
2023-04-28

浅析Linux中的零拷贝技术的使用

本文探讨Linux中主要的几种零拷贝技术以及零拷贝技术适用的场景。为了迅速建立起零拷贝的概念,我们拿一个常用的场景进行引入: 引文##在写一个服务端程序时(Web Server或者文件服务器),文件下载是一个基本功能。这时候服务端的任务是:
2022-06-03

Linux零拷贝技术的用法

这篇文章主要讲解了“Linux零拷贝技术的用法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux零拷贝技术的用法”吧! 1、为什么需要零拷贝  传统的 Linux 系统的标
2023-06-05

linux下的零拷贝技术介绍

本篇内容主要讲解“linux下的零拷贝技术介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“linux下的零拷贝技术介绍”吧!传统的数据传输方式很长一段时间内,数据拷贝的认识仅仅停留在应用程序层
2023-06-13

Linux中零拷贝技术是什么

这篇文章给大家分享的是有关Linux中零拷贝技术是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。引文在写一个服务端程序时(Web Server或者文件服务器),文件下载是一个基本功能。这时候服务端的任务是:将
2023-06-15

kafka零拷贝技术怎么应用

Kafka零拷贝技术是一种优化技术,可以提高数据传输的效率,减少数据在内存和磁盘之间的拷贝次数。它的应用主要体现在以下几个方面:发送端零拷贝:Kafka通过使用操作系统级别的发送接口(如sendfile或writev),将数据从磁盘直接发送
2023-10-27

golang零拷贝技术怎么使用

Go语言中的零拷贝技术主要通过使用unsafe.Pointer和reflect.SliceHeader来实现。下面是一个使用零拷贝技术的简单示例:package mainimport ("fmt""reflect""unsafe")fu
2023-10-23

零拷贝Zero-Copy技术如何理解

这篇文章将为大家详细讲解有关零拷贝Zero-Copy技术如何理解,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。 1.前言今天和大家一起学习个底层技术点-零拷贝Zero-Copy。Linux系
2023-06-15

详谈Linux写时拷贝技术(copy-on-write)必看篇

COW技术初窥 在linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制”技术,也就是只有进程空间的各段的内容要发生变化时,才将父进程的内容复制一份给
2022-06-04

浅谈android中数据库的拷贝

SQLiteDatabase不支持直接从assets读取文件,所以要提前拷贝数据库。在读取数据库时,先在项目中建立assets文件夹用于存放外部文件,将数据库文件拷到该目录下。 代码方法:/*** 拷贝数据库至file文件夹下* @para
2022-06-06

Linux如何实现写时拷贝技术

这篇文章主要介绍了Linux如何实现写时拷贝技术,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。COW技术初窥在linux程序中,fork()会产生一个和父进程完全相同的子进程
2023-06-09

在linux系统中实现零拷贝的方法

在linux系统中实现零拷贝的方法?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是Linux系统Linux是一种免费使用和自由传播的类UNIX操作系统,是一
2023-06-07

好程序员技术分享浅谈JavaScript中的闭包

好程序员技术分享浅谈JavaScript中的闭包,js闭包是指有权访问另一个函数作用域中的变量的函数,个人认为js闭包最大的用处就是防止对全局作用域的污染。 试想如果我们把一些仅仅只用到一两次的变量都声明在全局作用域中,最后肯定是容易出错且
2023-06-03

浅谈钩子技术在windows操作系统上的安全应用

钩子技术在Windows操作系统上具有广泛的应用,包括安全领域。钩子技术可以用于监控和拦截系统中的各种操作,从而实现对系统的安全控制和保护。以下是钩子技术在Windows操作系统上的安全应用的一些示例:1. 键盘钩子:通过键盘钩子可以监控用
2023-08-25

浅谈微软和苹果各自的字体平滑,反锯齿,和次像素渲染技术

苹果公司和微软公司,对于如何在电脑屏幕上显示字体,总是有不同看法。目前,这两家公司都使用次像素渲染(subpixel rend编程客栈ering)技术,使得字体在低分辨率的屏幕上,也能显得很清晰。这两家公司的根本不同之处在于指导思想。 *
2023-05-24

编程热搜

目录