`
xuela_net
  • 浏览: 494411 次
文章分类
社区版块
存档分类
最新评论

Linux网络处理“零拷贝”技术&mmap()&内核进程间通信设计&8086分页管理——摆在一起来谈谈

 
阅读更多

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其实是共享内存的一般使用模式”这样的话,说明你把握到关键点了。

分享到:
评论

相关推荐

    Linux内核源代码情景分析 (上下册 高清非扫描 )

    第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用...

    Linux进程间通信.zip

    Linux进程间通信(fifo/pipe/mmap)后续将会完成进程间通信(消息队列/信号) 请关注

    mmap内核驱动与应用程序

    里面包括 1. 一个用户空间的mmap将文件映射到内存进行操作的例子 2. 一个mmap内核驱动及对应的mmap用户空间的程序。

    UNIX网络编程 卷2:进程间通信

    第一部分 简介  第1章 简介 2  1.1 概述 2  1.2 进程、线程与信息共享 3  1.3 IPC对象的持续性 4  1.4 名字空间 5  1.5 fork、exec和exit对IPC对象的影响 7  1.6 出错处理:包裹函数 8  1.7 Unix标准 9  ...

    linux 内核源代码分析

    第7章 基于socket的进程间通信 7.1 系统调用socket() 7.2 函数sys—socket()——创建插口 7.3 函数sys—bind()——指定插口地址 7.4 函数sys—listen()——设定server插口 7.5 函数sys—accept()——接受...

    Linux内核mmap保护机制研究.pdf

    Linux内核mmap保护机制研究.pdf

    mmap.rar_linux 例程_linux 内存映射_linux内核例程_mmap内核_supplyfru

    这个linux下,实现内核内存地址映射到用户空间例程

    mmap相关内核框架解析

    原作者Sung-hun Kim,比较有价值。 the original author is Sung-hun, thanks for his contribution and spirit of sharing.

    linux mmap文件内存映射机制

    mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而 Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享...

    《UNIX网络编程 第2版. 第2卷, 进程间通信(中文版)》(W·Richard Stevens[美] 著)

    两卷本的《UNIX网络编程》是已故著名技术作家W. Richard Stevens的传世之作。卷2着重讨论如何让应用程序与在其他机器上的应用程序进行对话。良好的进程间通信(IPC)机制是提高UNIX程序性能的关键。本书全面深入地...

    linux内核源代码情景分析

    《linux内核源代码情景分析》(非扫描电子版本) 第1章 预备知识 1.1 Linux内核简介 1.2 Intel X86 CPU系列的寻址方式 1.3 i386的页式内存管理机制 1.4 Linux内核源代码中的C语言代码 1.5 Linux内核源代码中的...

    linux zero copy mmap

    linux zero copy mmap

    Linux网络编程 视频 教程

    Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输...

    Linux内核情景分析(二级标题).pdf

    第1章 预备知识 1.1 Linux内核简介 1.2 Intel X86 CPU 系列的寻址方式 1.3 i386的页式内存管理机制 ...第7章 基于socket的进程间通信 第八章 设备驱动 第9章 多处理器的SMP系统结构 第10章 系统的引导和初始化

    linux操作系统内核技术-uestc课件

     1掌握处理器在进程地址空间上的三种运行位置,了解内核编程不能使用C库函数和FPU,以及可能产生内存故障、核心栈溢出和四种内核竞争情形的原因。(2学时)  2熟悉进程描述符的组织,进程上下文和进程状态转换,和...

    linux 系统源码全面剖析

    零拷贝技术 虚拟内存空间管理 中断机制 硬件相关 中断处理 系统调用 文件系统 虚拟文件系统 MINIX文件系统 通用块层 直接I/O 原生异步I/O inotify源码分析 进程间通信 信号处理机制 共享内存 网络 Socket接口 Unix ...

    linux内核驱动和用户态通信代码

    这里面的代码提供了内核驱动的样例,并且提供了通过mmap,在用户态和内核态之间构建共享内存,来进行通信的方法

    Linux内核情景分析

    第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6. 5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 《LINUX内核源代码情景分析(下册)》图书...

    UNIX网络编程 卷2 进程间通信 带完整书签,完整目录

    10.12 进程间共享信号量 205 10.13 信号量限制 206 10.14 使用FIFO实现信号量 206 10.15 使用内存映射I/O实现信号量 210 10.16 使用System V信号量实现Posix信号量 218 10.17 小结 224 习题 225 第11章 ...

Global site tag (gtag.js) - Google Analytics