背景技术
现代网络通信中,数据包的延时、吞吐量不大等问题导致网络通信性能的下降,尤其是在高性能计算(HPC,High-performance computing)中,高性能计算:通常是指使用很多处理器(作为单个机器的一部分)或者某一集群中组织的几台计算机的计算系统和环境。现有许多类型的高性能计算(HPC)系统,其范围从标准计算机的大型集群到高度专用的硬件。现有大多数基于集群的高性能计算(HPC)系统使用高性能网络互连,比如那些来自InfiniBand或Myrinet的网络互连。基本的网络拓扑和组织可以使用一个简单的总线拓扑,在性能很高的环境中,网状网络系统在主机之间提供较短的潜伏期,所以可改善总体网络性能和传输速率。尽管网络拓扑、硬件和处理硬件在高性能计算(HPC)系统中很重要,但是使系统如此有效的核心功能是由操作系统和应用软件提供的。
高性能计算(HPC)系统使用的是专门的操作系统,这些操作系统被设计为看起来像是单个计算资源,其中有一个控制节点,该节点形成了高性能计算(HPC)系统和客户机之间的接口。在这些网络通信中,很多计算机节点的网卡是基于TCP/IP协议来实现的,当应用程序从套接口把数据发送到网卡驱动程序的过程中,需要把数据拷贝很多次,这样的话,在高性能通信的时候,数据包发送的瓶颈就出现了。为了从根本上解决此问题,可以采用零拷贝技术,即减少数据从应用程序到网络设备传递过程中的拷贝次数,减少系统调用,实现CPU的零参与,彻底消除CPU在这方面的负载。
零拷贝(zero-copy):所谓零拷贝是指数据包从应用程序到网络设备传递的过程中,减少数据拷贝次数,减少系统调用,实现CPU的零参与,彻底消除CPU在这方面的负载。
然而,现有的零拷贝技术中,有些是针对专用的以太网驱动,其零拷贝模块是针对特定的某类网卡实现的,应用范围受到很大的限制,有些即使是针对通用的以太网驱动,可是,其实现过程是基于内核中缓存的,它的零拷贝模块的数据缓存区域是和用户共享,即内核和用户共享一个数据区域,耗费资源大,数据拷贝的次数没有得到最大程度的减少,不能很好地满足高性能计算(HPC)系统的需求。还有的零拷贝模块是基于TCP/IP协议的,TCP/IP协议是通用的以太网协议,由于跨越多层协议、存储分配、保护机制等原因耗费资源比较大。
发明内容
为了解决上述的问题,本发明在用户发送数据的时候采用零拷贝技术,即把用户的数据直接拷贝到驱动程序中去,然后发送,以增大网络系统数据传递的吞吐量,减少网卡数据在从用户空间传递过程中的延时。
本发明提供了一种通用网卡非缓存的零拷贝方法,其包括以下步骤:
(1)于用户空间内进行内存注册,建立应用程序的buffer;
(2)把应用程序的buffer附加到新建的skbuf上;
(3)经过通用网卡,内核函数把skbuf中的数据发送出去。
其中步骤(2)包含如下具体步骤:
(21)把buffer的虚拟地址转换成物理地址;
(22)把该物理地址处的内容传给skbuf。
并且,在采用非缓存的零拷贝方式发送数据之前,具体是在步骤(1)于用户空间内进行内存注册,建立应用程序的buffer之后、步骤(2)把应用程序的buffer附加到新建的skbuf上之前,本发明采用MX协议为零拷贝提供数据传递的支持。
其中于步骤(1)中,于用户空间建立该数据缓存区域,即在用户空间申请一块存储单元,并将这些存储单元转化成物理页面,并用标记标注,将需要被发送的数据存放到了这个存储单元上去即存储到物理页面上。
其中步骤(2)将最后发送的数据存储在结构体skbuf中。
本发明还提供了一种通用网卡非缓存的零拷贝系统,包含一个运行于内核的零拷贝模块,该零拷贝模块包含:
处理和响应用户层的接收和发送的事件的发送核心模块;
锁住被使用页的锁页管理模块;
用来管理虚拟存储器、物理存储器的控制线路的MMU通知模块;
其中,MMU通知模块将用户层的发送接口传来的虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权。该零拷贝系统还包括一个零拷贝库,该零拷贝库设置于用户层并提供该零拷贝模块与用户层的通信接口。
该零拷贝库中还实现了自身的MX通信协议,MX通信协议的变量是以分散的形式分布于零拷贝库中的不同结构体,并负责数据的传递与连接,零拷贝库中的函数把正确的数据包传递给该零拷贝模块。
该零拷贝模块与该零拷贝库是通过rpm包的形式安装于现有系统,并分别运行于内核与用户层中。
该零拷贝库包括发送接口以及区域管理模块,应用程序调用该发送接口申请用户空间,该区域管理模块对被申请的用户内存空间进行管理。
本发明是采用非缓存方式,即直接把用户空间的数据通过一系列过程传递给通用网卡中的结构体skbuf。由于零拷贝模块是运行于内核空间的,因而零拷贝过程是发生于内核空间,且数据非缓存区域位于用户空间,耗费资源小;相对于现有的零拷贝模块所采用的耗费资源较大的数据缓存区域和用户共享的方法,本发明更适用于所有通用网卡,可以实现局域网内大的吞吐量的数据传递,以完成高性能计算(HPC)通信的功能。
具体实施方式
为了使本发明所采用的技术、手段及其优点,现举优选实施例并配合附图详述如后,此仅供说明之用,在专利申请上并不受此种结构的限制。
本发明主要是为了解决在通用的网卡驱动中数据传输吞吐量的问题,尤其是当最大传输单元(MTU)大于或等于9000的时候,采用零拷贝技术后的数据传输性能会显著提高。
本发明于本实施例中主要是借助由用户空间的MX协议代替内核空间的TCP/IP协议,实现从用户空间到内核空间的零拷贝,把应用程序的buffer固定(即pinning)到物理页面上。这一过程包括首先需要进行内存注册,该数据缓存区域位于用户空间,即在用户空间内申请一块存储单元,将这些存储单元转化成物理页面,并用标记标注,将需要被发送的数据存放到这个存储单元上去,亦即存储到物理页面上。然后把该应用程序的buffer附加到新建的skbuf上,即把buffer的虚拟地址转换成物理地址,再把物理地址的内容传给skbuf。这个注册和地址转化的过程在linux里用零拷贝函数就可以实现了,消耗资源很小。最后,经过通用网卡,内核函数把skbuf中的数据发送出去,也就是直接把固定在物理内存里的buffer的数据发送出去,从而整个发送过程实现零拷贝,其中:skbuf是指Linux中采用socket buffer作为存储和管理数据包的数据结构,简称skbuf。
本发明的零拷贝模块是运行于通用的以太网网卡驱动程序之上的,其在系统中的布局图如附图1所示。本发明主要是增加了用于实现本发明的非缓存方式的零拷贝方法的,且位于用户空间的零拷贝库11以及运行于内核中的零拷贝模块12,于本实施例中,首先安装现有的系统及驱动,当系统安装好后,再以rpm包的形式安装零拷贝模块12以及零拷贝库11,并分别运行于内核与用户层中,借助零拷贝库11的支持,并与现有的通用以太网层13、以太网驱动模块14以及以太网硬件15的配合,就可以实现局域网内部大的吞吐量的数据传递,完成高性能计算(HPC)通信的功能。
其中,零拷贝库11存在于用户层,零拷贝模块12存在于内核层,在linux系统调用中用户层的库函数会调用内核层的函数。当发送方要实现零拷贝的时候,发送方的应用程序调用零拷贝库11,零拷贝库11再调用零拷贝模块12中的函数。因此,零拷贝库11和零拷贝模块12的关系是调用与被调用的关系。
其中,本发明中的零拷贝模块12是针对Linux下所有以太网网卡驱动程序实现的,参见图1所示,本发明的本实施例中的零拷贝模块12中使用的协议不是TCP/IP协议,而是在零拷贝库中实现了MX协议,该协议是独立于TCP/IP协议层的、是零拷贝模块服务的专有协议,跨越的层次少,耗费资源少,通信速度快;而且,零拷贝模块12是运行于内核空间,零拷贝过程是发生于内核空间,而数据非缓存区域位于用户空间,耗费资源小。
其中,零拷贝库11主要是为应用程序的函数调用服务的,其提供零拷贝模块与用户层的通信接口,为用户编程提供了通道,另外这个库中还实现了自身的MX通信协议,而不是TCP/IP协议。其中,MX协议的变量是以分散的形式分布于零拷贝库中的不同结构体,并负责数据的传递与连接,零拷贝库11中的函数把正确的数据包传递给零拷贝模块12进行解析、处理和传送。如附图2所示,MX协议包括用户空间的三个结构体:结构体1:struct_request,负责数据的发送和接收,结构体2:struct_partner,管理记录发送方和接收方的信息,结构体3:struct_endpoint,记录本地的网卡信息,通常是将结构体1:struct_request的请求配合结构体2:struct_partner的参数传递给结构体3:struct_endpoint,最后根据真实发送消息的大小来调用不同的函数类型并发送该消息,零拷贝模块12只需处理应用程序36和零拷贝库11发送过来的命令消息。零拷贝库11中实现的MX协议只是负责数据包的正确发送和接收,并填充数据包的各个阶段所需要的字段,最后对这些字段描述符赋值之后,让零拷贝模块12去解析处理。
其中,零拷贝模块12主要是实现了用户空间的数据拷贝和相关设备描述符的分配等,把用户应用程序分配的缓存区计算成要发送给网卡驱动程序的页面,然后把这些页的地址存储并锁定标记,最后把这些数据直接从用户空间发送到网卡设备。附图3是零拷贝模块的组图,它是以组件的形式存在于内核中。发送接口34指的是发送接口的API函数,负责数据的通信接口,其可以被应用程序36所调用;区域管理模块35用于管理申请的非缓存区域(如用户空间);发送核心模块31响应发送的事件;锁页管理模块33记录哪些页面被使用,即锁住;MMU通知模块32(内存管理单元)是CPU(中央处理器)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责将虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权。
具体描述来说是这样的,在零拷贝库11初始化的时候,调用mmap()函数映射五个空间,分别是驱动描述符、发送队列、接收队列、期望事件队列和不期望事件队列。应用程序36调用发送接口34中的函数net_isend()去发送数据,发送接口34中的函数net_isend()调用net__alloc_request()申请用户空间。在申请用户空间的过程中,区域管理模块35使用结构体net_region_user描述用户区域,使用结构体net_segment_region_user描述区域中的段,使用枚举net_status_region_user描述区域的状态,使用结构体net_state_pin_region_user描述区域是否被锁住。MMU通知模块32中调用函数net_region_segment_add_user()中的PAGE_ALIGN将用户空间传递过来的虚拟地址转变成物理页,并将该物理页纳入区域的管理范围内。然后,发送接口34调用net_req_isend()为内核准备数据,调用ioctl()函数向内核发送命令。在驱动程序中,锁页管理模块33根据发送接口34向内核发送的创建区域的命令来调用锁页函数,函数net_pin_full_immediate_region_user()用来锁住整个区域的页,函数net_wait_pin_parallel_region_user()用来等待锁住区域被释放,函数net_init_region_demand_pin_user()用来完成区域的初始化工作,函数net_pin_demand_region_continue_user()用来锁住尚未被锁住的页,函数net_finish_demand_region_pin_user()表示该区域已经完成锁住。
在零拷贝模块12中,发送核心31调用函数net_skb_new()申请skbuf空间,在发送数据之前,将skbuf中的自定义协议填充,调用函数net_header_mac_skb()进行头处理,调用函数net_segments_from_copy()把用户区域的数据拷贝到skbuf中,调用函数net__peer_target_set()设置数据包的发送对(peer),最后调用net_queue_xmit()将数据发送出去。
如附图4所示为本发明的数据发送过程中实现零拷贝的流程图,其中,MX协议为零拷贝提供数据传递的支持,在本实施例中是以现有的MX协议为例说明的,熟知该域技术的本领域技术人员可知,为实现零拷贝提供数据传递的支持也可以依该些需求使用其它类似的协议甚或自行定义数据传输协议来实施。
零拷贝模块12中的各个组成模块在数据发送过程中的作用体现在:当数据发送时,首先由发送接口34申请用户空间,然后区域管理模块35对被申请的用户内存空间进行管理,即完成内存注册(步骤40);MMU通知模块32将用户buffer的虚拟地址转化成物理地址(步骤411);锁页管理模块33判断被转化后的物理页面是否被锁住,若锁住则该物理地址被引用,否则该物理地址未被引用,即表示该物理地址声明无效;发送核心模块31把物理地址的内容传给skbuf(步骤412),这里的物理地址指的是被引用的物理地址;最后,发送核心模块31调用通用网卡的发送函数把skbuf中的数据发送出去(步骤42)。
为了实现数据发送时候的零拷贝,具体需要经过如下步骤,如附图4所示:
1)内存注册(步骤40):内存空间最多可分为256个区域,每个区域是由很多个段组成,一个区域最大空间是4M,用户空间申请4M的内存区域,为以后数据的传送提供了空间,通过函数mmap()把这4M区域空间映射成零拷贝模块12所需要的发送队列、接收队列、期望事件队列、不期望事件队列和设备端点描述符这几个段。每个段是由很多个物理页面组成,这些物理页面分为锁住的和没有锁住的,用户空间通过ioctl函数向驱动程序发送命令锁住自己的区域,应用程序36把用户空间中的数据发送到这些被锁住的页面上,并按字节存放。这一过程的主要特点是数据非缓存区域位于用户空间,即在用户空间内申请一块存储单元,将这些存储单元转化成物理页面,并用标记标注,将需要被发送的数据存放到了这个存储单元上去即存储到物理页面上;
2)把应用程序的buffer附加到新建的skbuf上(步骤41):在本实例中,包括以下两个步骤:
①把buffer的虚拟地址转换成物理地址(步骤411):通过函数获取用户空间的虚拟地址并计算转变成物理地址,这个物理地址是被保存在了一个结构体的变量中,还有该结构体的其他相关变量记录了该物理地址中的物理页面使用了多少字节、锁住页面与否等信息。在本实施例中,虚拟地址转变成物理页面的过程是把从“虚拟地址”开始的“虚拟地址长度”的这么长的连续空间转变成由页指针去指向物理页面的开始位置处。在这个转变的过程中,真实的虚拟地址是被保存到了一个变量中,然后库函数把这个变量传递给零拷贝模块去处理这个被变量保存的虚拟地址。之后,零拷贝模块就可以计算出物理页面的大小和分布情况,最后由页面指针指向这些连续的页面。
②把物理地址的内容传给skbuf(步骤412):网卡的驱动程序把被锁住页面上的内容拷贝到skbuf这个结构体中对应指针的位置处。
3)经过通用网卡,内核函数把skbuf中的数据发送出去(步骤42):把已经锁住的物理页上的数据填充到skbuf结构体中去并由内核函数把这个结构体数据发送出去。
相比于现有的缓存方式,如附图5b所示,其是把用户空间数据先存入共享区域,再将共享区域的数据传递给网卡中的结构体skbuf,本发明是采用非缓存方式,即直接把用户空间的数据通过一系列过程传递给通用网卡中的结构体skbuf,如附图5a所示。由于零拷贝模块12是运行于内核空间,因而零拷贝过程是发生于内核空间,且数据非缓存区域位于用户空间,耗费资源小;相对于现有的零拷贝模块12所采用的耗费资源较大的数据缓存区域和用户共享的方法,本发明可以实现局域网内大的吞吐量的数据传递,以完成高性能计算(HPC)通信的功能。