网卡的零拷贝理解

转自:http://blog.csdn.net/freas_1990/article/details/9173713

 

 

Jack:最近听说了网络处理的“零拷贝”技术,觉得非常神奇,在网上查阅了很多资料。不过,并不是太明白——知其然,而不知其所以然。你能通俗地解释一下吗?

我:这是一个相对比较复杂的话题,说起来话就多了。本质上来说,其实就是80386的分页管理变异而已。

Jack:分页管理?这个跨度有点大,穿越了。

我:你觉得穿越,是因为你基础不过关。基础不过关,看技术就像看天书。如果你“本源技术”学得很好,那些看是玄妙的技巧,一眼就可以看破

Jack:为什么说“零拷贝”技术的本质是80386的分页管理变异的呢?

我:我们先说一说,零拷贝技术的本质是什么吧。当一个网络数据包通过网卡进入内核,然后再进入用户空间的时候,至少会经过2次data copy。不要小看两次data copy——互联网行业的网络服务器的CPU资源80%都消耗在这2次数据copy上去了,基本上别的事情都做不了。而事实上,这样的数据拷贝完全是没有必要的——这个数据包从网卡到内核再到用户空间,这个拷贝的过程仅仅起到了“传输”的作用,而数据包内容没有任何变化。零拷贝技术正是解决这两次拷贝。它能让两次拷贝完全消除,一次都不拷贝。

Jack:消除这两次拷贝的关键点在哪里呢?

我:这里需要分开讨论。第一次数据拷贝发生在“网卡到内核”。网卡到内核这种说法算是比较边缘性的。专业一点的说法是,外部设备到主存储器的数据传输。这个概念听着熟悉吧?

Jack:是的。这让我想起了外部设备到主存的三种数据传输方式——轮询、中断、DMA。其中轮询太龊了,基本上没有实用价值,而DMA适合在数据传输比较大的情况下使用,而且需要该外部设备支持。一般情况下,中断的方式用得比较多。

我:是的。中断是操作系统的神经中枢。不过,如果要实现零拷贝技术,这个网卡一定要采用DMA技术。

Jack:为什么呢?即便采用了DMA技术,数据任然要从网卡拷贝到主存,并不能算作“零拷贝”。

我:是的。使用DMA技术,仍然需要把数据从网卡拷贝到主存——但是,拷贝的过程中,CPU是完全不需要参与的。既然CPU不参与,就不会有任何CPU资源消耗,data copy带来的损耗就可以避免开了,所以这一层的data copy就被cut了

Jack:明白了。那内核到用户空间的数据拷贝是怎么消除的呢?

我:我先不回答这一个问题。我先问一个问题,数据如何从内核拷贝到用户空间呢?

Jack:从CPU层面来说,内核与用户空间处于不同的段(segment),段间数据拷贝,必须要有一个起中转作用的段寄存器参与才行。

我:是的。386CPU有fs寄存器充当这样的角色。

Jack:但是,如何才能实现段间数据共享呢?

我:从CPU的内存管理的角度来说,这是不可能实现的。Intel的设计就是段与段间分隔开来,每个段有自己的存储空间、属性等。

Jack:那从CPU的内存管理的角度来说,“零拷贝”岂不是完全不能实现?

我:是的。不仅不能实现,“零拷贝”的思想与操作系统内核的设计思想、CPU的设计思想是完全背道而驰的,属于妖孽那一类。

Jack:不要卖关子了。直接说吧,Linux内核是如何做到“零拷贝”的呢?

我:消除从Linux内核到用户空间的数据拷贝的关键点在于80386的虚拟内存机制——这是CPU层面的技术,并不是操作系统层面的技术。从Linux内核的设计角度来讲,它天生就认为从网卡到内核到用户空间的2次数据拷贝是必须的,拷贝了两次才是完整的(尽管做了无用功、在网络流量比较大的情况下性能低下,但是站在Linux内核的角度,它就要这么做)。而“零拷贝”技术正是打破了操作系统的设计理念,妖孽了一把,从CPU层面打破Linux内核与用户空间的阻隔,使其内存共享

Jack:CPU的这种功能具体是什么呢?

我:就是80386的虚拟内存管理与分页机制的组合。虚拟内存可以通过页目录、页表映射到物理内存地址,也可以直接映射到物理磁盘上(的文件)去。关键点就在这里了。既然虚拟内存可以映射到文件上去,而文件又是多个进程共享的(不用区分内核与用户进程),内核的某一块内存区域映射到一个文件,而用户进程(server进程)又关联到这一个文件,那么这个用户进程(server进程)就可以直接操作Linux内核的某块内存区域了。如果内核中的这块内存区域再被设定为网卡DMA映射的内存区,“零拷贝”也就实现了。

Jack:Linux为这种操作系统设计了API吗?

我:有的。mmap()就是做这个事儿的。而实际上,Unix进程间通信的“共享内存”方式,其本质原理,也是这个。

Jack:明白了,作为一个操作系统内核,其设计理念势必把内核与用户进程区分开来,而各个用户进程的内存区域也必然是互相隔离的。这样,才是真正的进程的概念。进程间需要通信,最“正当”的方式是在内核区域构建相应的数据结构,某进程需要通信就通过系统调用进入内核区域,修改代码,然后通知到需要通信的进程。被通知的进程通过系统调用进入内核空间,通信完成。如果进程间需要进行数据传输,只能先通过A进程传输到内核,然后再从内核传输到B进程,期间必然发生至少2次数据拷贝

我:是的。

Jack:但是。“共享内存”mmap本质上借用了80386的虚拟内存管理模式,打破了操作系统的设计思想。而mmap其实是共享内存的一般使用模式

我:是的。能说出“而mmap其实是共享内存的一般使用模式”这样的话,说明你把握到关键点了。

<think>好的,我现在需要帮用户理解零拷贝文件传输的概念和原理,并且给出通俗的解释和工作原理。首先,我得回忆一下自己之前学过的相关知识,确保理解正确,然后结合用户提供的引用内容来组织回答。 用户给出的引用内容里提到了几个关键点:零拷贝并不是零次复制,而是减少不必要的数据拷贝次数。比如,用户提到,传统的数据传输需要两次拷贝,从网卡到内核再到用户空间,而零拷贝技术可以消除这两次拷贝。引用中还有关于网络服务器CPU资源消耗主要在数据拷贝上的问题,零拷贝技术能解决这个问题。 首先,我需要用通俗的语言解释零拷贝。可能用快递包裹的比喻比较合适,比如包裹不需要经过多个中转站直接送到目的地,减少中间的搬运次数。这样用户更容易理解。 接下来,要分步骤说明传统文件传输的问题。传统的流程应该是:磁盘→内核缓冲区→用户缓冲区→socket缓冲区→网卡。这里涉及到四次上下文切换和两次CPU拷贝,两次DMA拷贝。这样效率低,因为用户态和内核态的切换以及数据复制消耗资源。 然后,说明零拷贝技术如何优化这个过程。比如使用sendfile系统调用,或者内存映射(mmap),减少拷贝次数。比如mmap将内核缓冲区和用户缓冲区共享,省去一次拷贝;sendfile更进一步,连用户态都不需要参与,直接在内核完成数据到socket的传输,甚至可以利用DMA gather技术让网卡直接从内核缓冲区取数据,实现零次CPU拷贝。 需要注意的是,用户引用中提到零拷贝并不是完全没有复制,而是减少不必要的复制次数。比如可能还有DMA的拷贝,但CPU不再参与复制,从而节省CPU资源。这点需要明确,避免用户误解。 然后,可能还需要提到零拷贝的应用场景,比如高性能服务器、大文件传输、视频流媒体等,这样用户知道在什么地方使用该技术。 最后,生成相关问题。根据用户之前的示例,可能需要问及零拷贝与传统拷贝的区别、实现方式、应用场景、优缺点等。但需要确保问题符合用户的学习路径,帮助深入理解。 在回答过程中,需要引用用户提供的引用内容,比如引用[3]提到两次数据拷贝消耗80%的CPU资源,零拷贝解决这个问题。引用[1]和[2]纠正了零拷贝不等于零复制的错误说法,所以要在回答中强调这一点,确保概念正确。 另外,检查是否有技术细节错误,比如DMA的作用,上下文切换的次数,sendfile和mmap的区别等。确保信息准确,避免误导用户。 可能还需要比较不同的零拷贝技术,比如mmap和sendfile的区别,以及DMA gather的功能,这样用户能全面了解不同层次的优化。 总结下来,回答的结构应该是:通俗解释→传统传输的问题→零拷贝的解决方案(分步骤)→技术实现(如sendfile)→优点和应用场景→相关问题。同时,正确引用用户提供的资料,确保信息可靠。</think>### 零拷贝文件传输的通俗解释及工作原理 #### 通俗解释 零拷贝文件传输可以理解为**“快递包裹直达”**的优化过程。想象你网购的商品需要经过多个中转站才能到达手中,而零拷贝技术相当于让商品直接从仓库发到你家,跳过了所有中间环节。虽然实际运输过程中仍有物理移动(数据传输),但减少了不必要的分拣和搬运(数据复制),从而大幅提升效率[^3]。 --- #### 传统文件传输的问题 传统方式传输文件(如从磁盘发送到网络)需要经过以下步骤: 1. **磁盘 → 内核缓冲区**(DMA拷贝) 2. **内核缓冲区 → 用户缓冲区**(CPU拷贝) 3. **用户缓冲区 → Socket缓冲区**(CPU拷贝) 4. **Socket缓冲区 → 网卡**(DMA拷贝) 此过程涉及**4次上下文切换**(用户态↔内核态)和**2次CPU拷贝**,导致CPU资源被大量消耗在数据搬运上(占服务器CPU资源的80%[^3])。 --- #### 零拷贝的核心原理 零拷贝通过**减少数据复制次数**和**避免用户态参与**来优化性能,具体技术包括: 1. **`mmap`内存映射** - 将内核缓冲区与用户缓冲区**映射到同一块内存**,省去第2步的CPU拷贝。 - 但仍需第3步的CPU拷贝(内核→Socket缓冲区)。 2. **`sendfile`系统调用** - 文件直接在内核空间从磁盘传输到Socket缓冲区,**完全跳过用户态**。 - 进一步减少到**2次DMA拷贝** + **0次CPU拷贝**。 3. **DMA Gather(分散-聚集)** - 网卡直接从内核缓冲区读取数据,彻底消除所有CPU拷贝,实现真正的“零拷贝”[^3]。 --- #### 技术对比 | 技术 | CPU拷贝次数 | 上下文切换次数 | |--------------|-------------|----------------| | 传统方式 | 2 | 4 | | `mmap` | 1 | 4 | | `sendfile` | 0 | 2 | --- #### 应用场景 1. 高频网络通信(如HTTP服务器、消息队列) 2. 大文件传输(视频流、云存储) 3. 高并发场景(减少CPU资源竞争) ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值