框架篇:小bai也能秒懂的Linux零拷贝原理,Linux运维面试题整理

本文介绍如何通过零拷贝技术优化Linux运维学习,包括内核空间与用户空间的交互、DMA在I/O操作中的应用,以及JavaNIO的零拷贝实现。作者分享了一份全面的系统化学习资料,旨在帮助程序员高效提升技能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
img

正文

  • 内核空间:Linux自身使用的空间;主要提供进程调度、内存分配、连接硬件资源等功能

  • 用户空间:提供给各个程序进程的空间;用户空间不具有访问内核空间资源的权限,如果应用程序需要使用到内核空间的资源,则需要通过系统调用来完成:从用户空间切换到内核空间,完成相关操作后再从内核空间切换回用户空间

缓冲区和虚拟内存

========

  • 直接内存访问(Direct Memory Access)(DMA)

  • 直接内存访问:DMA允许外设设备和内存存储器之间直接进行IO数据传输,其过程不需要CPU的参与

  • 缓冲区 是所有I/O的基础,I/O 无非就是把数据移进或移出缓冲区

  • 进程发起read请求,内核先检查内核空间缓冲区是否存在进程所需数据,如果已经存在,则直接copy数据到进程的内存区。如果没有,系统则向磁盘请求数据,通过DMA写入内核的read缓冲冲区,接着再将内核缓冲区数据copy到进程的内存区

  • 进程发起write请求,则是把进程的内存区数据copy到内核的write缓冲区,然后再通过DMA把内核缓冲区数据刷回磁盘或者网卡中

  • 虚拟内存:现代操作系统都使用虚拟内存,有如下两个好处

  • 一个以上的虚拟地址可以指向同一个物理内存地址

  • 虚拟内存空间可大于实际可用的物理地址

  • 利用第一点特性可以把内核空间地址和用户空间的虚拟地址映射到同一个物理地址,这样DMA就可以填充(读写)对内核和用户空间进程同时可见的缓冲区了;大致如下

传统的 I/O

=======

#include

ssize_t write(int filedes, void *buf, size_t nbytes);

ssize_t read(int filedes, void *buf, size_t nbytes);

复制代码

  • 如java在linux系统上,读取一个磁盘文件,并发送到远程端的服务

  • 1)发出read系统调用,会导致用户空间到内核空间的上下文切换,然后再通过DMA将文件中的数据从磁盘上读取到内核空间缓冲区

  • 2)接着将内核空间缓冲区的数据拷贝到用户空间进程内存,然后read系统调用返回。而系统调用的返回又会导致一次内核空间到用户空间的上下文切换

  • 3)write系统调用,则再次导致用户空间到内核空间的上下文切换,将用户空间的进程里的内存数据复制到内核空间的socket缓冲区(也是内核缓冲区,不过是给socket使用的),然后write系统调用返回,再次触发上下文切换

  • 4)至于socket缓冲区到网卡的数据传输则是独立异步的过程,也就是说write系统调用的返回并不保证数据被传输到网卡

「一共有四次用户空间与内核空间的上下文切换。四次数据copy,分别是两次CPU数据复制,两次DMA数据复制」

mmap+write实现的零拷贝

================

#include <sys/mman.h>

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)

复制代码

  • 1)发出mmap系统调用,导致用户空间到内核空间的上下文切换。然后通过DMA引擎将磁盘文件中的数据复制到内核空间缓冲区

  • 2)mmap系统调用返回,导致内核空间到用户空间的上下文切换

  • 3)这里不需要将数据从内核空间复制到用户空间,因为用户空间和内核空间共享了这个缓冲区

  • 4)发出write系统调用,导致用户空间到内核空间的上下文切换。将数据从内核空间缓冲区复制到内核空间socket缓冲区;write系统调用返回,导致内核空间到用户空间的上下文切换

  • 5)异步,DMA引擎将socket缓冲区中的数据copy到网卡

「通过mmap实现的零拷贝I/O进行了4次用户空间与内核空间的上下文切换,以及3次数据拷贝;其中3次数据拷贝中包括了2次DMA拷贝和1次CPU拷贝」

sendfile实现的零拷贝

==============

#include <sys/sendfile.h>

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

复制代码

  • 1)发出sendfile系统调用,导致用户空间到内核空间的上下文切换,然后通过DMA引擎将磁盘文件中的内容复制到内核空间缓冲区中,接着再将数据从内核空间缓冲区复制到socket相关的缓冲区

  • 2)sendfile系统调用返回,导致内核空间到用户空间的上下文切换。DMA异步将内核空间socket缓冲区中的数据传递到网卡

「通过sendfile实现的零拷贝I/O使用了2次用户空间与内核空间的上下文切换,以及3次数据的拷贝。其中3次数据拷贝中包括了2次DMA拷贝和1次CPU拷贝」

带有DMA收集拷贝功能的sendfile实现的零拷贝

==========================

  • 从Linux 2.4版本开始,操作系统提供scatter和gather的SG-DMA方式,直接从内核空间缓冲区中将数据读取到网卡,无需将内核空间缓冲区的数据再复制一份到socket缓冲区

  • 1)发出sendfile系统调用,导致用户空间到内核空间的上下文切换。通过DMA引擎将磁盘文件中的内容复制到内核空间缓冲区

  • 2)这里没把数据复制到socket缓冲区;取而代之的是,相应的描述符信息被复制到socket缓冲区。该描述符包含了两种的信息:A)内核缓冲区的内存地址、B)内核缓冲区的偏移量

  • 3)sendfile系统调用返回,导致内核空间到用户空间的上下文切换。DMA根据socket缓冲区的描述符提供的地址和偏移量直接将内核缓冲区中的数据复制到网卡

「带有DMA收集拷贝功能的sendfile实现的I/O使用了2次用户空间与内核空间的上下文切换,以及2次数据的拷贝,而且这2次的数据拷贝都是非CPU拷贝。这样一来我们就实现了最理想的零拷贝I/O传输了,不需要任何一次的CPU拷贝,以及最少的上下文切换」

java提供的零拷贝方式

============

  • java NIO的零拷贝实现是基于mmap+write方式

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

给大家整理的电子书资料:

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)
[外链图片转存中…(img-DpGv5nAv-1713616053554)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值