CN113064846A - 基于Rsockets协议的零拷贝数据传输方法 - Google Patents

基于Rsockets协议的零拷贝数据传输方法 Download PDF

Info

Publication number
CN113064846A
CN113064846A CN202110399487.5A CN202110399487A CN113064846A CN 113064846 A CN113064846 A CN 113064846A CN 202110399487 A CN202110399487 A CN 202110399487A CN 113064846 A CN113064846 A CN 113064846A
Authority
CN
China
Prior art keywords
function
request
memory
address
sending
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
CN202110399487.5A
Other languages
English (en)
Inventor
黄旺
刘亚萍
张硕
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Central South University
Peng Cheng Laboratory
Original Assignee
Central South University
Peng Cheng Laboratory
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Central South University, Peng Cheng Laboratory filed Critical Central South University
Priority to CN202110399487.5A priority Critical patent/CN113064846A/zh
Publication of CN113064846A publication Critical patent/CN113064846A/zh
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F13/00Interconnection of, or transfer of information or other signals between, memories, input/output devices or central processing units
    • G06F13/14Handling requests for interconnection or transfer
    • G06F13/20Handling requests for interconnection or transfer for access to input/output bus
    • G06F13/28Handling requests for interconnection or transfer for access to input/output bus using burst mode transfer, e.g. direct memory access DMA, cycle steal
    • HELECTRICITY
    • H04ELECTRIC COMMUNICATION TECHNIQUE
    • H04LTRANSMISSION OF DIGITAL INFORMATION, e.g. TELEGRAPHIC COMMUNICATION
    • H04L69/00Network arrangements, protocols or services independent of the application payload and not provided for in the other groups of this subclass
    • H04L69/26Special purpose or proprietary protocols or architectures

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Computing Systems (AREA)
  • Computer Security & Cryptography (AREA)
  • Computer Networks & Wireless Communication (AREA)
  • Signal Processing (AREA)
  • Memory System Of A Hierarchy Structure (AREA)

Abstract

本发明公开了一种基于Rsockets协议的零拷贝数据传输方法,目的是消除拷贝开销。技术方案是先构建由基于Rsockets协议的RDMA传输系统,内存管理模块,内存处理模块,工作请求模块组成的零拷贝数据传输系统。发送端和接收端套接字应用创建RDMA资源,内存管理模块和内存处理模块配合创建缓存池,建立对缓存池的内存映射,发送端套接字应用从发送缓存发送数据,内存管理模块和内存处理模块处理后得到物理地址和页个数,工作请求模块构造对应工作请求,RDMA网卡执行工作请求将数据发送到接收端缓存池,接收端内存管理模块将接收缓存与缓存池中数据物理地址建立内存映射,数据成功到达。本发明实现了零拷贝数据传输。

Description

基于Rsockets协议的零拷贝数据传输方法
技术领域
本发明涉及网络传输领域,特别涉及以RDMA(Remote Direct Memory Access,远程直接内存访问)为核心的高速数据传输方法。
背景技术
RDMA能够将数据从发送方的内存中直接传送到接收方的内存中,无需操作系统的参与,消耗的CPU资源也非常低。RDMA技术最早是出现在InfiniBand网络上,后面为了能够在以太网上使用RDMA技术,InfiniBand行业协会又提出了RoCE(RDMA over ConvergedEthernet,基于融合以太网的RDMA)技术。但与TCP/IP网络不同的是RoCE并不使用TCP/IP协议栈,而是主要继承了InfiniBand的通信协议,这导致RoCE无法直接在以TCP/IP网络为基础的数据中心部署,大部分的数据中心仍然以套接字(Socket)为核心的应用在运行,如果让套接字应用都改为RDMA应用,这将是一个庞大且复杂的工程。RoCE网络协议有类似OSI网络模型的物理层,链路层,网络层和传输层。物理层,链路层,网络层,传输层的协议都实现到网卡硬件上,避免操作系统的参与。而上层的软件部分,由OFA(Open Fabric Alliance)组织负责提供的统一的软件栈OFED(OpenFabrics Enterprise Distribution),该软件栈包括驱动,RDMA内核模块,RDMA库等功能。OFED提供的RDMA库称为Verbs。通过Verbs可以实现RDMA网络传输。下面介绍通过Verbs实现RDMA传输的主要方法。
RDMA网络传输方法则具体包括如下步骤:
第一步,获取RDMA设备链表,并选择其中一个RDMA设备,获取驱动传递上来的设备句柄。
第二步,通过Verbs创建相应的RDMA资源,具体为创建保护域(ProtectionDomain),保护域用于限制其他QP(Queue Pair)访问保护域内的内存和数据。创建完成队列(Completion Queue),完成队列用于通知每次RDMA传输的结果。创建队列对QP(QueuePair),队列对分为发送队列(Send Queue,SQ)和接收队列(Receive Queue,RQ),通过将传输任务发布到相关队列中,让网卡进行RDMA传输工作,发送数据例如SEND,WRITE,READ的工作请求发布到QP的发送队列中,接收发送方通过SEND操作发送的数据,需要提前将RECEVIE操作的工作请求发布到QP的接收队列中。注册内存区域(Memory Region),将需要发送或接收数据的内存信息及对应的物理地址信息注册到网卡中,并设置访问权限,由网卡计算并返回对应的key值,此后网卡在访问相关内存区域时,先获取到对应的key值,才会进行正确访问。
第三步,设置QP的状态为准备发送状态(即RTS(即Ready To Send))或准备接收状态(RTR(即Ready To Receive)),设置QP的相关属性包括发送队列长度,接收队列长度。如果是发送方,则将QP的状态设置为RTS,网卡才可以发送数据,而接收方则需要QP的状态为RTR,网卡就可以接收数据。在设置QP的状态过程中,发送方和接收方需要交换队列对序号(即QPN(Queue Pair Number))和包序号(即PSN(Packet Sequence Number))。
第四步,设置工作请求,并将工作请求发布到QP中,具体根据工作请求类型来决定发布到发送队列还是接收队列。并通知网卡有请求发送到QP中,请求网卡处理数据。
第五步,网卡根据工作请求的不同传输类型决定是发送(SEND),读(READ),写(WRITE),接收(RECEIVE)操作。对于SEND操作,发送方在工作请求中设置好发送方数据所在地址和长度,网卡得以访问发送方数据并发送到接收方,接收方先于发送方SEND操作前将RECEIVE工作请求发布到接收方QP的接收队列中,当发送方的数据到达接收方后,接收方的网卡从接收方QP的接收队列中获取RECEIVE工作请求,该工作请求规定了数据的接收地址和长度,接收方网卡将发送方的数据放置到数据的接收地址中。对于WRITE操作,发送方需要知道本地发送数据地址和长度,接收方接收数据地址和长度以及对应的key值,网卡将数据从发送方的发送数据地址发送到接收方的接收数据地址,中间无需操作系统干预,全部交由网卡完成。对于READ操作,发送方需要知道本地接收数据地址和接收方的数据地址以及对应的key值,网卡将这个请求包发送到接收方网卡中,接收方网卡根据请求中的接收方的数据地址,访问到对应的数据,并返回给发送方的本地接收数据地址。中间同样无需操作系统干预,交由网卡完成。
第六步,网卡产生完成事件(即CQE(Completion Queue Event))到完成队列里,用户通过轮询完成队列来获取完成事件,通过解析完成事件来获取工作请求的完成情况。
Rsockets(RDMA socket API,RDMA的套接字应用程序调用接口)是一个在RDMA网络上提供套接字接口的协议,是linux-rdma小组提供的librdmacm的库的一部分,也是属于OFED库的一部分。Rsockets的主要工作是实现在RDMA提供的接口Verbs语义上适配所有的套接字调用,以便使用RDMA网络。
在Linux系统中,一般的使用套接字传输的应用可以通过Rsockets协议来使用RDMA进行数据传输。图1为套接字应用使用Rsockets协议进行RDMA传输的逻辑关系图。Linux系统将自身划分为两部分,一部分为内核空间,一部分为用户空间,用户空间的代码运行在较低的特权级别上,只允许使用部分系统资源,不能使用某些特定的系统功能,也不能直接访问内核空间和硬件设备。而内核空间运行的是一部分核心软件,运行在较高的特权级别上,拥有访问硬件的所有权限。其中套接字应用和OFED库安装在用户空间,Rsockets协议属于OFED库,因此也安装在用户空间,OFED内核库安装在内核空间,RDMA网卡为硬件,安装在主机的PCIE插槽内。发送端和接收端都安装有套接字应用,OFED库,OFED内核库以及RDMA网卡。
如图1所示,发送端和接收端的套接字应用将socket请求传递给Rsockets协议,Rsockets协议将socket请求转为对应的RDMA资源请求,并通过OFED库传递给OFED内核库,OFED内核库处理Rsockets协议传来的RDMA资源请求,将RDMA资源请求构造为RDMA硬件资源请求,传递给RDMA网卡。RDMA网卡获取到RDMA硬件资源请求后,在网卡内部分配对应的RDMA硬件资源给OFED内核库;OFED内核库对RDMA硬件资源进一步处理为RDMA资源,将RDMA资源传递回OFED库;OFED库将RDMA资源传递给Rsockets协议;Rsockets协议将对应的RDMA资源转为socket资源,将socket资源返回给发送端和接收端的套接字应用。随后,发送端的套接字应用将发送缓存地址传递给Rsockets协议,Rsockets协议接收到发送缓存地址后将数据从发送缓存拷贝到Rsockets协议的sbuf中,RDMA网卡访问sbuf的数据,将数据发送到接收端的RDMA网卡上,接收端的RDMA网卡将数据拷贝到Rsockets协议的rbuf中,Rsockets协议将数据从rbuf中拷贝到接收端的套接字应用的接收缓存中。其中套接字应用的socket请求包括创建套接字(socket),绑定套接字(bind),侦听套接字(listen),接收连接(accept),请求连接(connect),发送(write、send、sendto),接收(read、recv、recvfrom)。对应的socket资源则包括套接字索引,socket请求的执行状态。
Rsockets协议的具体步骤如图2所示
第一步,发送端和接收端套接字应用传递socket请求,创建RDMA资源。
1.1发送端和接收端套接字应用调用socket函数,使用Rsockets协议拦截socket函数,Rsockets协议的rsocket函数替代socket函数,rsocket函数创建rsocket对象,rsocket对象用来存储套接字索引,存储RDMA资源,存储sbuf、rbuf的地址和大小。初始化rsocket对象,设置sbuf、rbuf的大小。rsocket函数根据socket函数传入的参数type(指定传输是流传输还是数据报传输类型)和protocol(指定是TCP协议还是UDP协议)来确认是TCP还是UDP传输,如果是TCP传输,则跳到1.1.1。如果是UDP传输,则跳到1.1.2。
1.1.1 rsocket函数调用OFED库的rdma_create_id函数分配连接管理ID号(即cm_id),连接管理ID号用于建立和管理RDMA连接,如果从发送端获取的type和protocol,是发送端套接字应用,转1.2,如果从接收端获取的type和protocol,是接收端套接字应用,转1.3。
1.1.2 rsocket函数创建一个UDP套接字,如果从发送端获取的type和protocol,是发送端套接字应用,转2.2,如果从接收端获取的type和protocol,是接收端套接字应用,转1.3。
1.2发送端套接字应用调用Linux系统的connect函数,使用Rsockets协议拦截connect函数,采用Rsockets协议的rconnect函数替代connect函数,rconnect函数调用Rsockets协议的rs_do_connect函数创建RDMA资源请求,经由OFED库处理和OFED内核库处理后,得到RDMA资源,将RDMA资源处理为对应的socket资源,传递回发送端的套接字应用,rs_do_connect函数为sbuf、rbuf分配内存空间,向接收端套接字应用发送连接请求,与接收端套接字应用交换连接信息,设置rsocket状态为已连接状态。转第二步。
1.3接收端套接字应用调用Linux系统的bind函数,使用Rsockets协议拦截bind函数,采用Rsockets协议的rbind函数替代bind函数,如果是TCP传输,转1.3.1,如果是UDP传输,转1.3.2。
1.3.1 rbind函数调用OFED库的rdma_bind_addr函数将连接管理ID号和对应的IP地址绑定。转1.4
1.3.2 rbind函数调用Rsockets协议的ds_init_ep函数创建RDMA资源请求,经由OFED库和OFED内核库处理得到RDMA资源,采用Linux系统的malloc函数为sbuf、rbuf创建内存空间。随后rbind函数调用Linux系统的bind函数绑定UDP套接字,转第二步的2.4。
1.4接收端套接字应用调用Linux系统的listen函数,使用Rsockets协议拦截listen函数,采用Rsockets协议的rlisten函数替代listen函数,rlisten函数调用OFED库的rdma_listen函数对连接管理ID号所绑定的IP地址进行侦听,获取发送端套接字应用的连接请求,转1.5。
1.5接收端套接字应用接收到连接请求后,接收端套接字应用调用Linux系统的accept函数,使用Rsockets协议拦截accept函数,采用Rsockets协议的raccept函数替代accept函数。raccept函数分配一个新的rsocket对象,通过1.1创建的rsocket对象初始化新的rsocket对象,raccept函数随后侦听发送端套接字应用的连接请求,当raccept接收到连接请求,raccept调用rs_create_ep为新的rsocket对象创建RDMA资源,采用Linux系统的malloc函数为sbuf、rbuf分配内存空间,与发送端套接字应用交换连接信息。设置新的rsocket对象状态为已连接,转第二步的2.3。
第二步,发送端套接字应用发送数据,接收端套接字应用接收数据
2.1发送端套接字应用调用Linux系统的write或send函数,使用Rsocket协议拦截write或send函数,采用Rsockets协议的rsend函数替代write或send函数,rsend函数判断当前rsocket对象的状态是否是已连接状态,如果不是已连接,转2.1.1。如果是已连接,转2.1.2。
2.1.1 rsend函数调用Rsockets协议的rs_do_connect函数建立连接,如果rs_do_connect函数返回失败则“显示发送端和接收端连接失败”,转2.5,如果rs_do_connect返回成功,转2.1.2。
2.1.2 rsend函数调用Rsockets协议的rs_can_send函数判断当前sbuf的大小是否为0和RDMA资源中的队列对空间是否为0,如果sbuf不为0且队列对空间不为0,则可以发送数据,否则不能发送数据。如果不能发送数据,则转2.1.3。如果能发送数据,转2.1.4。
2.1.3 rsend函数调用Rsockets协议的rs_get_comp获取完成队列的完成事件,如果能从完成队列获取到完成事件,从完成事件中获取sbuf的事件和队列对的事件,增加sbuf的大小和RDMA资源的队列对空间大小,则转2.1.2,如果无法从完成队列获取到完成事件则显示“获取完成事件失败,空间不足”,转2.5。
2.1.4 rsend函数根据sbuf剩余空间计算发送长度,将数据从发送端套接字应用的发送缓存地址拷贝到sbuf地址中,构造RDMA WRITE工作请求发送sbuf的数据,通知RDMA网卡,RDMA网卡访问sbuf地址获取数据,并发送到接收端的RDMA网卡,接收端的RDMA网卡将数据放置到Rsockets协议的rbuf中。如果发送端套接字应用发送缓存中的数据没有发送完,转2.1.2。如果发送端套接字应用发送缓存中的数据发送完,转2.5。
2.2发送端套接字应用调用Linux系统的sendto函数,使用Rsockets协议拦截sendto函数,采用Rsockets协议的rsendto函数替代sendto函数,rsendto函数判断当前rsocket对象是否为初始状态,如果是初始状态,转2.2.1。如果不是初始状态,转2.2.2
2.2.1 rsendto函数调用Rsockets协议的ds_init_ep函数创建RDMA资源请求,经由OFED库和OFED内核库处理得到RDMA资源,ds_init_ep函数调用Linux系统的malloc函数为rsocket对象的sbuf创建内存空间,为属于RDMA资源中的QP的rbuf创建内存空间,设置rsocket对象为可发送和接收状态,转2.2.2。
2.2.2 rsendto函数判断发送端套接字应用调用Linux系统的sendto函数中传入的地址是否已经被解析且该地址对应的RDMA资源是否被创建,如果没有解析或者创建对应的RDMA资源,rsendto函数调用Rsockets协议的ds_get_dest函数解析传入地址获取路径,并设置来自传入的地址的数据默认可以接收,如果针对传入的地址没有创建对应的RDMA资源,则ds_get_dest函数调用ds_init_ep函数创建RDMA资源,如果针对传入的地址已经创建了RDMA资源则不再调用ds_init_ep函数,ds_get_dest函数调用Linux系统的malloc函数为属于该RDMA资源中的QP的rbuf创建内存空间,转2.2.3。
2.2.3 rsendto函数调用Rsockets协议的dsend函数,其具体步骤为dsend函数调用Rsockets协议的ds_can_send函数判断当前sbuf的大小是否为0和RDMA资源中的队列对空间是否为0,如果sbuf不为0且队列对空间不为0,则可以发送数据,否则不能发送数据。如果不能发送数据,转2.2.4。如果能发送数据,转2.2.5。
2.2.4 rsendto函数调用Rsockets协议的ds_get_comp函数从完成队列中获取完成事件,如果从完成队列中无法获取到完成事件,则显示“无法获取完成事件,空间不足”,转2.5。如果从完成队列中获取到完成事件,从完成事件中获取sbuf的事件和队列对的事件,增加sbuf的大小和RDMA资源的队列对空间大小。转2.2.3.
2.2.5 rsendto将数据从发送端套接字应用发送缓存中拷贝到sbuf空间中。构造工作请求,操作类型为SEND,网卡将数据从sbuf空间中发出,接收端网卡接收到数据后,消耗接收端的RECEIVE工作请求,将数据放置到RECEIVE工作请求中指定的接收端QP的rbuf位置中。如果发送端套接字应用的发送缓存中的数据发送完成,则转2.5,如果发送端套接字应用的发送缓存中的数据未发送完成,则转2.2.3。
2.3接收端套接字应用调用Linux系统的read或recv函数,使用Rsockets协议拦截read或recv函数,采用Rsockets协议的rrecv函数替代read或recv函数,rrecv函数判断当前rsocket对象的状态是否是已连接状态,如果不是已连接,执行2.3.1。如果是已连接,转2.3.2
2.3.1 rrecv函数调用Rsockets协议的rs_do_connect函数建立连接,如果rs_do_connect函数失败则显示“发送端和接收端建立连接失败”,转2.5。如果rs_do_connect函数成功,转2.3.2。
2.3.2 rrecv函数调用Rsockets协议的rs_have_rdata判断rbuf中是否有未处理的数据,如果没有未处理的数据,转2.3.3,如果有未处理的数据,转2.3.4。
2.3.3 rrecv函数调用rs_get_comp,轮询完成队列后获取完成事件,如果获取到完成事件,解析完成事件来得知是否有新数据到达以及数据的长度,如果解析完成事件获知有新数据达到,rbuf增加完成事件中数据的长度,转2.3.2。如果获取完成事件失败,则“显示获取完成事件失败,接收数据失败”,转2.5。
2.3.4 rrecv函数计算接收数据的长度,将数据从接收缓存rbuf拷贝到接收端套接字应用的接收缓存中。如果接收端套接字应用接收数据完成,则转2.5。如果接收端套接字应用接收数据未完成,转2.3.2。
2.4接收端套接字应用调用Linux系统的recvfrom函数,使用Rsockets协议拦截recvfrom函数,采用Rsockets协议的rrecvfrom函数会替代recvfrom函数,rrecvfrom函数调用Rsockets协议的ds_recvfrom函数接收数据,转2.4.1。
2.4.1 ds_recvfrom函数调用rs_have_data判断rbuf空间中是否有未处理的数据,如果没有数据,转2.4.2,如果有数据,转2.4.3,
2.4.2 ds_recvfrom函数调用ds_get_comp函数获取完成事件,如果获取到完成事件,解析完成事件来得知是否有新数据到达以及数据的长度,如果解析完成事件获知有新数据达到,rbuf增加完成事件中数据的长度,转2.4.1,如果获取完成事件失败,则“显示获取完成事件失败,接收数据失败”,转2.5。
2.4.3 ds_recvfrom函数将数据从rbuf空间中拷贝到接收端套接字应用的接收缓存中。转2.5。
2.5结束。
虽然Rsockets提供了对套接字应用较好的兼容性,但Rsockets并没有完全发挥出RDMA的性能优势,从上述流程可以知道,无论是以TCP传输还是UDP传输而言,发送端套接字应用需要将数据从发送端套接字应用的发送缓存拷贝到Rsockets协议的sbuf中,以便网卡能够将数据从sbuf中发送到接收端的Rsockets协议的rbuf中,并再将数据从rbuf中拷贝到接收端套接字应用的接收缓存中,这样发送和接收都存在一次拷贝,一次传输过程总共存在两次拷贝开销。在传输大量数据时,拷贝开销会明显对传输性能造成影响。并且目前还没有基于Rsockets协议实现的零拷贝传输方法的公开报导。
发明内容
本发明要解决的技术问题在于提出一种基于Rsockets协议的零拷贝数据传输方法,基于Rsockets协议的具体步骤,消除Rsockets协议存在的拷贝开销,进一步提高基于Rsockets协议传输数据的性能。
本发明的技术方案是:使用网卡允许使用物理地址直接发送数据的功能、Linux系统提供的内存映射功能、写时复制机制功能来实现基于Rsockets协议下的零拷贝数据传输,将数据从数据所在的物理地址上直接发送,并在接收端应用的内存中直接接收,无需拷贝,以提高Rsockets协议传输数据的性能。
本发明具体包含如下步骤:
第一步,构建基于Rsockets协议的零拷贝数据传输系统。基于Rsockets协议的零拷贝数据传输系统由图1所示的基于Rsockets协议的RDMA传输系统(包括套接字应用,OFED库,OFED内核库以及RDMA网卡),内存管理模块,内存处理模块,工作请求模块组成。发送端和接收端都安装有基于Rsockets协议的零拷贝数据传输系统。
与图1一样,基于Rsockets协议的RDMA传输系统中,套接字应用和OFED库安装在用户空间,Rsockets协议属于OFED库的一部分,因此也安装在用户空间,OFED内核库安装在内核空间,RDMA网卡为硬件,安装在主机的PCIE插槽内。
为了适应零拷贝和新添加的模块,需要修改Rsockets协议中的相关函数:在Rsockets协议中添加SEND发送管理函数,在Rsockets协议的rsendto函数中增加调用SEND发送管理函数的功能,SEND发送管理函数负责发送工作请求模块构造的SEND工作请求;在Rsockets协议中添加WRITE发送管理函数,在Rsockets协议的rsend函数增加调用WRITE发送管理函数的功能,WRITE发送管理函数负责发送工作请求模块构造的WRITE工作请求;Rsockets协议的rconnect函数、raccept函数、rsendto函数,rrecvfrom函数增加调用OFED库的注册物理地址内存区域函数的功能,使得具有注册物理地址内存区域的功能;在Rsockets协议中增加请求创建缓存池函数,在Rsockets协议增加调用请求创建缓存池函数的功能,请求创建缓存池函数向内存管理模块发送“创建缓存池请求”;在Rsockets协议中增加请求内存处理函数,在rsend函数和rsendto函数中增加调用请求内存处理函数的功能,请求内存处理函数向内存管理模块发送“内存处理请求”和内存地址信息;在Rsockets协议中增加请求RDMA资源函数,在rsend函数和rsendto函数增加调用请求RDMA资源函数的功能,请求RDMA资源函数向工作请求模块发送“RDMA资源请求”;在Rsockets协议中增加判断缓存池函数,在rsend函数中增加调用判断缓存池函数的功能,向内存管理模块发送“判断缓存池长度请求”;在Rsockets协议中增加WRITE处理完成事件函数,在rrecv函数增加调用WRITE处理完成事件函数的功能,负责处理WRITE工作请求的消息的接收,并向内存管理模块发送“内存映射请求”;在Rsockets协议中增加SEND处理完成事件函数,在rrecvfrom函数增加调用SEND处理完成事件函数的功能,负责处理SEND工作请求的消息的接收,SEND处理完成事件函数向内存管理模块发送“内存映射请求”;在Rsockets协议中增加请求接收工作请求函数,在rbind函数增加调用请求接收工作请求函数的功能,请求接收工作请求函数向工作请求模块发送RDMA资源和“构造接收工作请求”;在Rsockets协议增加获取工作请求函数,在rsend函数和rsendto函数增加调用获取工作请求函数的功能,获取工作请求函数向工作请求模块发送“获取工作请求”。
内存管理模块运行在用户空间,与工作请求模块,内存处理模块以及OFED库的Rsockets协议相连,负责管理套接字应用的发送缓存和接收缓存以及缓存池。缓存池仅用于存储接收的数据,并提供数据所在的物理地址使得套接字应用的接收缓存可以与数据所在的物理地址建立内存映射,直接获取数据。当内存管理模块从请求创建缓存池函数接收到“创建缓存池请求”时,向内存处理模块发送“创建缓存池请求”,并从内存处理模块接收缓存池的物理地址,当内存管理模块接收到缓存池的物理地址,向内存管理模块发送“建立内存映射请求”,并从内存处理模块接收缓存池的虚拟地址。当内存管理模块从交换缓存池地址函数接收到“交换缓存池请求”时,发送端内存管理模块和接受端内存管理模块互相交换缓存池地址信息。当内存管理模块从请求内存处理函数接收到“内存处理请求”时,向内存处理模块发送“内存处理请求”,并从内存处理模块接收到物理地址和页个数,向工作请求模块返回物理地址和页个数。当内存管理模块从判断缓存池函数接收到“判断缓存池长度请求”时,内存管理模块计算缓存池长度,将缓存池长度返回给rsend函数。内存管理模块从WRITE处理完成事件函数接收到“内存映射请求”时,向内存处理模块发送“建立内存映射请求”,并从内存处理模块接收到套接字应用的发送缓存的虚拟地址。当内存管理模块从SEND处理完成事件函数接收到“内存映射请求”时,向内存处理模块发送“建立内存映射请求”,并从内存处理模块接收到套接字应用的发送缓存的虚拟地址。
内存处理模块运行在Linux系统的内核空间,与内存管理模块相连接,由两个部分组成,一个是提供内存处理功能的系统调用处理模块,一个是提供创建缓存池和内存映射功能的字符设备。系统调用处理模块负责处理从内存管理模块接收的“内存处理请求”,向内存管理模块发送物理地址和页个数。字符设备负责处理从内存管理模块接收的“创建缓存池请求”,创建一个缓存池,向内存管理模块返回缓存池的物理地址,缓存池可设置为16MB;字符设备处理从内存管理模块接收“建立内存映射请求”,建立内存映射,向内存管理模块传递与缓存池的物理地址对应的虚拟地址。
工作请求模块运行在用户空间,与内存管理模块和Rsockets协议相连接,负责构造对应的工作请求,将工作请求交由Rsockets协议处理。工作请求模块从Rsockets协议中获取RDMA资源,从内存管理模块获取内存的物理地址和页个数,构造基于物理地址发送的工作请求,并将基于物理地址发送的工作请求发送给Rsockets协议。当工作请求模块从请求接收工作请求函数收到RDMA资源和“构造接收工作请求”时,创建RECEIVE工作请求,将RECEIVE工作请求发送给Rsockets协议。当工作请求模块从获取工作请求函数接收到“获取工作请求”时,创建工作请求结构体数组,向rsend函数或rsendto函数发送创建的工作请求结构体数组地址和数组的长度。当工作请求模块从请求RDMA资源函数接收到“RDMA资源请求”时,判断工作请求模块是否获取到了RDMA资源,如果没有获取到RDMA资源,则向Rsockets协议发送“RDMA资源请求”以获取RDMA资源。
第二步,发送端和接收端的套接字应用向Rsockets协议发送socket请求,创建RDMA资源。内存管理模块和内存处理模块相互配合创建缓存池,建立对缓存池的内存映射,方法是:
2.1发送端和接收端套接字应用调用Linux系统的socket函数,使用Rsockets协议拦截socket函数,采用Rsockets协议中的rsocket函数替代socket函数,rsocket函数调用请求创建缓存池函数,请求创建内存池函数向内存管理模块发送“创建缓存池请求”。
2.2内存管理模块收到rsocket函数的“创建缓存池请求”,打开内存处理模块的字符设备,向内存处理模块的字符设备传递“创建缓存池请求”。
2.3内存处理模块的字符设备收到“创建缓存池请求”后,创建一个物理地址连续,大小为16MB的内存块作为缓存池,如果创建失败则显示“创建缓存池失败”,转3.32,如果创建成功,则向内存管理模块返回缓存池的物理地址和长度,转2.4。
2.4内存管理模块初始化内存管理结构体,内存管理结构体的内容包含缓存池物理地址首地址、缓存池虚拟地址首地址、长度、空闲长度、数据头指针、数据尾指针,内存管理模块将从字符设备接收的缓存池的物理地址和长度分别存入到内存管理结构体的缓存池物理地址首地址和长度中。而内存管理结构体的空闲长度初始化为内存管理结构体的长度,内存管理结构体的数据头指针初始化为零,内存管理结构体的数据尾指针初始化为零。
2.5内存管理模块构造“内存映射请求”,向内存处理模块的字符设备发送“内存映射请求”,请求映射缓存池物理地址。
2.6字符设备收到“建立内存映射请求”后,根据缓存池物理地址建立内存映射,调用Linux内核的remap_pfn_range函数将缓存池的物理地址与Linux内核查找的虚拟地址建立内存映射,将与缓存池的物理地址对应的Linux内核查找的虚拟地址返回给内存管理模块,内存管理模块将虚拟地址首地址写入内存管理结构体的缓存池虚拟地址首地址。
2.7 Rsockets协议的rsocket函数根据从发送端和接收端套接字应用调用的socket函数传入的参数type和protocol来确认是TCP还是UDP传输,如果是TCP传输,转2.7.1。如果是UDP传输,转2.7.2。
2.7.1如果是从发送端获取的type和protocol,说明是发送端套接字应用,由于是TCP传输的发送端套接字应用,需要调用Linux系统的connect函数建立连接,转2.8。如果是从接收端获取的type和protocol,说明是接收端套接字应用,由于是TCP传输的接收端套接字应用,需要调用Linux系统的accept函数接收发送端套接字应用的连接请求,转2.11。
2.7.2如果是从发送端获取的type和protocol,说明是发送端套接字应用,由于是UDP传输的发送端套接字应用,不需要建立连接,需要调用Linux系统的sendto函数发送消息,转3.16。如果是从发送端获取的type和protocol,说明是接收端套接字应用,由于是UDP传输的接收端套接字应用,需要调用Linux系统的bind函数绑定IP地址,转2.14。
2.8发送端套接字应用调用Linux系统的connect函数,使用Rsockets协议拦截connect函数,采用Rsockets协议的rconnect函数替代connect函数。rconnect函数调用交换缓存池地址函数,交换缓存池地址函数向发送端的内存管理模块发送“交换缓存池请求”。
2.9发送端的内存管理模块从rconnect函数接收“交换缓存池请求”,内存管理模块将发送端的内存管理结构体(命名为A1)的内容发送给接收端的内存管理模块,并等待接收端返回接收端的内存管理结构体(命名为A2),若发送端内存管理模块接收到A2,将A2存入到发送端的第二内存管理结构体(命名为B1)中,B1的内容包含接收端缓存池的物理地址首地址,接收端缓存池虚拟地址首地址,长度,空闲长度,数据头指针,数据尾指针。
2.10 Rsockets协议的rconnect函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域。转第三步。
2.11接收端套接字应用调用Linux系统的accept函数,使用Rsockets协议拦截accept函数,采用Rsockets协议的raccept函数替代accept函数。raccept函数调用交换缓存池地址函数,交换缓存池地址函数向接收端的内存管理模块发送“交换缓存池请求”。
2.12接收端的内存管理模块从raccept函数接收的“交换缓存池请求”,内存管理模块从发送端内存管理模块接收A1,将A1存入到接收端的第二内存管理结构体(命名B2)中,B2的内容包含发送端缓存池物理地址首地址,发送端缓存池虚拟地址首地址,长度,空闲长度,数据头指针,数据尾指针。接收端的内存管理模块将A2发送给发送端内存管理模块。
2.13 raccept函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域。转3.30。
2.14接收端套接字应用调用bind函数,使用Rsockets协议拦截bind函数,采用Rsockets协议的rbind函数替代bind函数,rbind函数调用请求接收工作请求函数,请求接收工作请求函数向工作请求模块发送Rsockets协议的rconnect函数创建的RDMA资源和“构造接收工作请求”。
2.15工作请求模块从rbind函数接收“构造接收工作请求”和RDMA资源,构造RECEIVE工作请求,设置目的地址为内存管理结构体(命名为A3)的缓存池虚拟地址,接收长度为2MB,共设置8个RECEIVE工作请求,第一个工作请求的目的地址为A3的发送端缓存池虚拟地址首地址,后面每个工作请求的目的地址依次增长2MB。工作请求模块调用OFED库的ibv_post_recv函数,将所有的RECEIVE工作请求发布到网卡中。转3.31。
第三步,发送端套接字应用从其发送缓存发送数据,内存管理模块和内存处理模块处理发送缓存后得到物理地址和页个数,工作请求模块构造对应工作请求,交由RDMA网卡执行工作请求将数据发送到接收端的缓存池中,接收端的内存管理模块将接收端套接字应用的接收缓存与缓存池中数据的物理地址建立内存映射,直接拿取数据。数据成功到达接收端套接字应用。方法是:
3.1发送端套接字应用调用write或send函数发送数据,使用Rsockets协议拦截write或send函数,采用Rsockets协议的rsend函数替代write或send函数,rsend函数调用请求内存处理函数,请求内存处理函数向发送端的内存管理模块发送“内存处理请求”,“内存处理请求”包含所在套接字应用发送缓存虚拟地址首地址,发送缓存的长度。
3.2发送端内存管理模块收到“内存处理请求”和内存地址信息,内存管理模块将内存地址信息处理为“内存处理请求”,向发送端的内存处理模块的系统调用处理模块传递“内存处理请求”。
3.3发送端的系统调用处理模块收到“内存处理请求”,从“内存处理请求”中获取到套接字应用发送缓存的虚拟地址和长度,调用Linux内核的get_user_pages函数处理套接字应用的发送缓存虚拟地址和发送缓存长度,得到发送端套接字发送缓存对应的物理地址和页个数,设置每个页不可交换,并且每个页是只读,使用链表存储物理地址,将存储物理地址的链表和页个数返回给发送端的内存管理模块。
3.4发送端的内存管理模块收到发送端的内存处理模块返回的存储物理地址的链表和页个数,使用地址管理结构体的物理地址链表头指针存储包含物理地址的链表的地址,地址管理结构体的页个数存储从内存处理模块返回的页个数,地址管理结构体包含物理地址链表头指针、页个数。
3.5 rsend函数调用请求RDMA资源函数,请求RDMA资源函数向发送端的工作请求模块发送“RDMA资源请求”。
3.6发送端的工作请求模块收到“RDMA资源请求”,工作请求模块判断是否已经获取RDMA资源,如果没有获取RDMA资源,向请求RDMA资源函数返回“RDMA资源请求”,请求RDMA资源函数收到“RDMA资源请求”后向发送端的工作请求模块发送RDMA资源,发送端的工作请求模块获取RDMA资源,转3.7。如果已经获取RDMA资源,则直接转3.7。
3.7发送端的工作请求模块从发送端的内存管理模块获取地址管理结构体和内存管理结构体B1,构造操作类型为WRITE的工作请求结构体,如果地址管理结构体的物理地址是连续的,转3.8。如果地址管理结构体的物理地址是离散的,转3.9。
3.8发送端的工作请求模块构造一个WRITE工作请求结构体数组,元素个数为1。设置工作请求结构体元素的源地址为地址管理结构体中的第一个物理地址,工作请求结构体元素的发送长度为地址管理结构体的页个数与Linux系统的页大小之积。转3.10
3.9发送端的工作请求模块构造一个WRITE工作请求结构体数组,数组元素个数为地址管理结构体的页个数。依次将地址管理结构体的链表的物理地址写入到工作请求结构体数组元素的源地址中,工作请求结构体数组的每个元素的发送长度为Linux系统页的大小。转3.10。
3.10 rsend函数调用获取工作请求函数,获取工作请求函数向发送端的工作请求模块发送“获取工作请求”。
3.11发送端的工作请求模块获取“获取工作请求”后,向rsend函数返回工作请求结构体数组的地址和数组元素个数。rsend函数接收工作请求结构体数组地址和数组长度。
3.12rsend函数调用判断缓存池函数,向发送端的内存管理模块发送“判断缓存池长度请求”。
3.13发送端的内存管理模块收到“判断缓存池长度请求”后,判断B1的空闲长度是否大于套接字应用的发送缓存的长度,如果B1的空闲长度小于套接字应用的发送缓存的长度,将B1的空闲长度返回给rsend函数,如果B1的空闲长度大于或等于套接字应用的发送缓存的长度,将套接字应用的发送缓存的长度返回给rsend函数。
3.14 rsend函数接收到3.13返回的长度,记为rsend函数的可发送长度,调用WRITE发送管理函数。
3.15 WRITE发送管理函数从rsend函数获取工作请求结构体数组的地址、数组元素个数、可发送长度,对获取的工作请求结构体数组,调用OFED库的ibv_post_send函数进行处理,具体方法如下:
3.15.1 WRITE发送管理函数从工作请求结构体数组取出元素,设置工作请求结构体数组元素的目的地址为B1的接收端缓存区的虚拟地址首地址,判断工作请求结构体数组元素的发送长度是否大于可发送长度,如果大于,转3.12。如果小于等于可发送长度,转3.15.2。
3.15.2 WRITE发送管理函数调用OFED库的ibv_post_send函数将取出的工作请求结构体元素发送到RDMA网卡。RDMA网卡从工作请求结构体数组元素的源地址读取数据,并发送到工作请求结构体数组元素的目的地址指定位置中,RDMA网卡发送数据的长度为工作请求结构体元素的发送长度。
3.15.3 WRITE发送管理函数将可发送长度减去工作请求结构体元素的发送长度,将B1的接收端缓存区虚拟地址首地址加上工作请求结构体元素的发送长度后存入B1的接收端缓存区虚拟地址首地址。转3.15.4。
3.15.4 WRITE发送管理函数判断工作请求结构体数组元素是否为空,如果为空,转3.32,如果不为空,转3.15.1。
3.16发送端套接字应用调用Linux系统的sendto函数,使用Rsockets协议拦截sendto函数,采用Rsockets协议的rsendto函数替代sendto函数,rsendto函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域,rsendto函数调用请求内存处理函数,请求内存处理函数向发送端的内存管理模块发送“内存处理请求”,“内存处理请求”包含所在套接字应用发送缓存虚拟地址首地址,发送缓存的长度。
3.17发送端的内存管理模块收到“内存处理请求”,向发送端的内存处理模块的系统调用处理模块传递“内存处理请求”。
3.18发送端的系统调用处理模块接收“内存处理请求”,系统调用处理模块从“内存处理请求”中获取到套接字应用发送缓存的虚拟地址和长度,系统调用处理模块处理套接字应用的发送缓存虚拟地址和发送缓存长度,得到对应的物理地址和页个数,设置每个页不可交换,并且设置每个页是只读,使用链表存储物理地址,将存储物理地址的链表和页个数返回给发送端的内存管理模块。
3.20发送端的内存管理模块收到发送端的内存处理模块返回的存储物理地址的链表和页个数,使用地址管理结构体的物理地址链表头指针存储包含物理地址的链表的地址,地址管理结构体的页个数存储从内存处理模块返回的页个数,地址管理结构体包含物理地址链表头指针,页个数。
3.21 rsendto函数调用请求RDMA资源函数,请求RDMA资源函数向发送端的工作请求模块发送“RDMA资源请求”。
3.22发送端的工作请求模块接收到“RDMA资源请求”,判断是否已经获取RDMA资源,如果没有获取RDMA资源,向请求RDMA资源函数返回“RDMA资源请求”,请求RDMA资源函数收到“RDMA资源请求”,向发送端的工作请求模块发送Rsockets协议的rsendto函数创建的RDMA资源,发送端的工作请求模块获取RDMA资源,转3.23。如果已经获取RDMA资源,直接转3.23。
3.23发送端的工作请求模块从发送端的内存管理模块获取地址管理结构体,构造操作类型为SEND的工作请求结构体,如果地址管理结构体的物理地址是连续的,转3.24。如果地址管理结构体的物理地址是离散的,转3.25。
3.24发送端的工作请求模块构造一个SEND工作请求结构体数组,元素个数为1。设置工作请求结构体数组元素的源地址为地址管理结构体中的第一个物理地址,工作请求结构体数组元素的发送长度为地址管理结构体的页个数与Linux系统的页大小之积。转3.26。
3.25工作请求模块构造一个SEND工作请求结构体数组,元素个数为地址管理结构体的页个数。依次将地址管理结构体的链表的物理地址写入到工作请求结构体数组的元素的源地址中,工作请求结构体数组的每个元素的发送长度为Linux系统页的大小。转3.26。
3.26 rsendto函数调用获取工作请求函数,获取工作请求函数向发送端的工作请求模块发送“获取工作请求”。
3.27发送端的工作请求模块获取“获取工作请求”,将工作请求结构体数组的地址和元素个数给返回给rsendto函数。
3.28 rsendto函数接收工作请求结构体数组地址和数组长度,rsendto函数调用SEND发送管理函数。
3.29 SEND发送管理函数从rsendto函数获取工作请求结构体数组的地址、数组长度,对获的工作请求结构体数组,进行如下处理:
3.29.1 SEND发送管理函数取出工作请求结构体数组元素。
3.29.2 SEND发送管理函数调用OFED库的ibv_post_send函数,将取出的工作请求结构体数组元素发送到RDMA网卡。RDMA网卡从工作请求结构体元素的源地址读取数据,将数据发送到接收端的RDMA网卡,接收端的RDMA网卡将发送端的数据放置到RECEIVE工作请求指定的位置中。
3.29.3 SEND发送管理函数判断工作请求结构体数组元素是否为空,如果为空,转3.32,如果不为空,转3.29.1。
3.30接收端套接字应用调用Linux系统的recv或者read函数接收数据,使用Rsockets协议拦截recv或read函数,采用Rsockets协议的rrecv函数替代recv或者read函数,rrecv函数调用WRITE处理完成事件函数,具体方法为:
3.30.1 WRITE处理完成事件函数调用OFED库提供的ibv_poll_cq函数获取完成事件,如果获取到完成事件,解析完成事件获取数据的长度,将内存管理结构体A2的数据尾指针的长度增加数据的长度,A2的数据头指针指向数据所在首地址,转3.30.2。如果没有获取到完成事件,则显示“获取完成失败,没有数据到达”,转3.32。
3.30.2 WRITE处理完成事件函数判断接收端套接字应用调用rrecv函数传入的长度是否大于3.30.1获取的数据长度,如果大于3.30.1获取的数据长度,记接收长度为数据长度,否则记接收长度为接收端套接字应用调用rrecv函数传入的长度。如果接收长度大于16KB,转3.30.3,如果接收长度小于或等于16KB,转3.30.5。
3.30.3 WRITE处理完成事件函数向接收端的内存管理模块发送“内存映射请求”。接收端的内存管理模块收到“内存映射请求”,处理为“建立内存映射请求”,向接收端的内存处理模块的字符设备传递“建立内存映射请求”。
3.30.4接收端的内存处理模块的字符设备收到“建立内存映射请求”,从“建立内存映射请求”中获取虚拟地址和物理地址、数据的长度,建立虚拟地址到物理地址的内存映射。转3.30.6。
3.30.5 WRITE处理完成事件函数将数据从数据所在地址拷贝到接收端套接字应用的接收缓存中。转3.30.6。
3.30.6 WRITE处理完成事件函数将A2的空闲长度增加接收的长度,A2的数据头指针增加接收长度的值,套接字应用的接收缓存的长度减去接收的长度,WRITE处理完成事件函数将A2的内容写到发送端的B1中。
3.30.7 WRITE处理完成事件函数判断套接字应用的接收缓存长度是否为零,如果为零,转3.32,如果不为零,转3.30.1。
3.31接收端套接字应用调用recvfrom函数,使用Rsockets协议拦截recvfrom函数,采用Rsockets协议的rrecvfrom函数替代recvfrom函数,rrecvfrom函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域,rrecvfrom函数调用SEND处理完成事件函数,具体方法为:
3.31.1 SEND处理完成事件函数调用OFED库提供的ibv_poll_cq函数获取完成事件,如果获取到完成事件,解析完成事件获取数据的长度,将内存管理结构体A2的数据尾指针的长度增加数据的长度,A2的数据头指针指向数据所在首地址,转3.31.2。如果没有获取到完成事件,则显示“获取完成事件失败,数据未到达”,转3.32。
3.31.2 SEND处理完成事件函数判断接收端套接字应用调用rrecv函数传入的长度是否大于3.31.1获取的数据长度,如果大于,记接收长度为数据长度,否则接收长度为接收端套接字应用调用rrecv函数传入的长度。如果接收长度大于16KB,转3.31.3,如果接收长度小于或等于16KB,转3.31.5。
3.31.3 SEND处理完成事件函数向接收端的内存管理模块发送“内存映射请求”。接收端的内存管理模块收到“内存映射请求”,处理为“建立内存映射请求”,向接收端的内存处理模块的字符设备传递“建立内存映射请求”。
3.31.4接收端的内存处理模块的字符设备收到“建立内存映射请求”,从“建立内存映射请求”中获取虚拟地址和物理地址,数据的长度,调用Linux内核的remap_pfn_range函数建立虚拟地址到物理地址的内存映射。转3.31.6。
3.31.5 SEND处理完成事件函数将数据从数据所在地址拷贝到接收端的套接字应用的接收缓存中。转3.31.6。
3.31.6 SEND处理完成事件函数将A2的空闲长度增加接收的长度,A2的数据头指针增加接收长度的值,套接字应用的接收缓存的长度减去接收的长度。转3.31.7。
3.31.7 SEND处理完成事件函数构造RECEIVE工作请求,工作请求的目的地址为A2的数据尾指针指向的地址,工作请求的长度为接收的长度,调用OFED库的ibv_poll_cq函数将RECEIVE工作请求发布到RDMA网卡中。转3.31.8。
3.31.8 SEND处理完成事件函数判断套接字应用的接收缓存长度是否为零,如果为零,转3.32,如果不为零,转3.31.1。
3.32结束。
采用本发明可以达到以下技术效果:
在TCP传输模式下,本发明的第三步中的内存管理模块和内存处理模块将发送缓存的虚拟地址和长度转化为对应的物理地址和长度,并设置了发送缓存对应的页为只读且不可交换。通过工作请求模块构造基于物理地址的WRITE工作请求,并传递物理内存区域给网卡,RDMA网卡会根据WRITE工作请求的源地址直接获取数据,并发送到接收端的RDMA网卡,接收端的RDMA网卡根据WRITE工作请求的目的地址,将数据放置到目的地址中,本发明的第三步中的3.30步中接收端的套接字应用在由内存管理模块向内存处理模块传递“建立内存映射请求”,使接收端套接字的接收缓存与数据所在地址直接建立内存映射,从发送端套接字应用的数据由RDMA网卡直接访问发送,接收端套接字应用通过内存映射直接访问数据,避免了拷贝的发生。
在UDP传输模式下,本发明的第三步中内存管理模块和内存处理模块将发送缓存的虚拟地址和长度转化为对应的物理地址和长度,并设置了发送缓存对应的页为只读且不可交换。通过工作请求模块构造基于物理地址的SEND工作请求,并传递物理内存区域给RDMA网卡,RDMA网卡根据SEND工作请求的源地址直接获取数据,并发送到接收端的RDMA网卡,接收端的RDMA网卡会将数据放置到RECEIVE工作请求指定的位置中。本发明的第三步中的3.31步接收端的套接字应用在由内存管理模块向内存处理模块传递“建立内存映射请求”,使接收端套接字的接收缓存与数据所在地址直接建立内存映射,从发送端套接字应用的数据由网卡直接访问发送,接收端套接字应用通过内存映射直接访问数据,避免了拷贝的发生。
本发明的3.3步和3.18步通过设置发送缓存对应的页只读且不可交换,发送端套接字应用在传输过程中如果马上写入发送缓存,会触发写时复制机制,写入的内容会写到新的物理页上,不会影响传输过程中的使用的物理页,保证数据传输过程中的安全。
附图说明
图1是背景技术所述的基于Rsockets协议的RDMA传输系统的逻辑结构图。
图2是背景技术所述的基于Rsockets协议的数据传输方法的总流程图。
图3是本发明于第一步构建的基于Rsockets协议的零拷贝数据传输系统的逻辑结构图。
图4是本发明总体流程图。
具体实施方式
下面对照附图对本发明进行进一步说明。
本发明总体流程如图4所示,包括以下步骤:
第一步,构建基于Rsockets协议的零拷贝数据传输系统。基于Rsockets协议的零拷贝数据传输系统如图3所示,由图1所示的基于Rsockets协议的RDMA传输系统(包括套接字应用,OFED库,OFED内核库以及RDMA网卡),内存管理模块,内存处理模块,工作请求模块组成。发送端和接收端都安装有基于Rsockets协议的零拷贝数据传输系统。
与图1一样,基于Rsockets协议的RDMA传输系统中,套接字应用和OFED库安装在用户空间,Rsockets协议属于OFED库的一部分,因此也安装在用户空间,OFED内核库安装在内核空间,RDMA网卡为硬件,安装在主机的PCIE插槽内。
为了适应零拷贝和新添加的模块,需要修改Rsockets协议中的相关函数:在Rsockets协议中添加SEND发送管理函数,在Rsockets协议的rsendto函数中增加调用SEND发送管理函数的功能,SEND发送管理函数负责发送工作请求模块构造的SEND工作请求;在Rsockets协议中添加WRITE发送管理函数,在Rsockets协议的rsend函数增加调用WRITE发送管理函数的功能,WRITE发送管理函数负责发送工作请求模块构造的WRITE工作请求;Rsockets协议的rconnect函数、raccept函数、rsendto函数,rrecvfrom函数增加调用OFED库的注册物理地址内存区域函数的功能,使得具有注册物理地址内存区域的功能;在Rsockets协议中增加请求创建缓存池函数,在Rsockets协议增加调用请求创建缓存池函数的功能,请求创建缓存池函数向内存管理模块发送“创建缓存池请求”;在Rsockets协议中增加请求内存处理函数,在rsend函数和rsendto函数中增加调用请求内存处理函数的功能,请求内存处理函数向内存管理模块发送“内存处理请求”和内存地址信息;在Rsockets协议中增加请求RDMA资源函数,在rsend函数和rsendto函数增加调用请求RDMA资源函数的功能,请求RDMA资源函数向工作请求模块发送“RDMA资源请求”;在Rsockets协议中增加判断缓存池函数,在rsend函数中增加调用判断缓存池函数的功能,向内存管理模块发送“判断缓存池长度请求”;在Rsockets协议中增加WRITE处理完成事件函数,在rrecv函数增加调用WRITE处理完成事件函数的功能,负责处理WRITE工作请求的消息的接收,并向内存管理模块发送“内存映射请求”;在Rsockets协议中增加SEND处理完成事件函数,在rrecvfrom函数增加调用SEND处理完成事件函数的功能,负责处理SEND工作请求的消息的接收,SEND处理完成事件函数向内存管理模块发送“内存映射请求”;在Rsockets协议中增加请求接收工作请求函数,在rbind函数增加调用请求接收工作请求函数的功能,请求接收工作请求函数向工作请求模块发送RDMA资源和“构造接收工作请求”;在Rsockets协议增加获取工作请求函数,在rsend函数和rsendto函数增加调用获取工作请求函数的功能,获取工作请求函数向工作请求模块发送“获取工作请求”。
内存管理模块运行在用户空间,与工作请求模块,内存处理模块以及OFED库的Rsockets协议相连,负责管理套接字应用的发送缓存和接收缓存以及缓存池。缓存池仅用于存储接收的数据,并提供数据所在的物理地址使得套接字应用的接收缓存可以与数据所在的物理地址建立内存映射,直接获取数据。当内存管理模块从请求创建缓存池函数接收到“创建缓存池请求”时,向内存处理模块发送“创建缓存池请求”,并从内存处理模块接收缓存池的物理地址,当内存管理模块接收到缓存池的物理地址,向内存管理模块发送“建立内存映射请求”,并从内存处理模块接收缓存池的虚拟地址。当内存管理模块从交换缓存池地址函数接收到“交换缓存池请求”时,发送端内存管理模块和接受端内存管理模块互相交换缓存池地址信息。当内存管理模块从请求内存处理函数接收到“内存处理请求”时,向内存处理模块发送“内存处理请求”,并从内存处理模块接收到物理地址和页个数,向工作请求模块返回物理地址和页个数。当内存管理模块从判断缓存池函数接收到“判断缓存池长度请求”时,内存管理模块计算缓存池长度,将缓存池长度返回给rsend函数。内存管理模块从WRITE处理完成事件函数接收到“内存映射请求”时,向内存处理模块发送“建立内存映射请求”,并从内存处理模块接收到套接字应用的发送缓存的虚拟地址。当内存管理模块从SEND处理完成事件函数接收到“内存映射请求”时,向内存处理模块发送“建立内存映射请求”,并从内存处理模块接收到套接字应用的发送缓存的虚拟地址。
内存处理模块运行在Linux系统的内核空间,与内存管理模块相连接,由两个部分组成,一个是提供内存处理功能的系统调用处理模块,一个是提供创建缓存池和内存映射功能的字符设备。系统调用处理模块负责处理从内存管理模块接收的“内存处理请求”,向内存管理模块发送物理地址和页个数。字符设备负责处理从内存管理模块接收的“创建缓存池请求”,创建一个缓存池,向内存管理模块返回缓存池的物理地址,缓存池可设置为16MB;字符设备处理从内存管理模块接收“建立内存映射请求”,建立内存映射,向内存管理模块传递与缓存池的物理地址对应的虚拟地址。
工作请求模块运行在用户空间,与内存管理模块和Rsockets协议相连接,负责构造对应的工作请求,将工作请求交由Rsockets协议处理。工作请求模块从Rsockets协议中获取RDMA资源,从内存管理模块获取内存的物理地址和页个数,构造基于物理地址发送的工作请求,并将基于物理地址发送的工作请求发送给Rsockets协议。当工作请求模块从请求接收工作请求函数收到RDMA资源和“构造接收工作请求”时,创建RECEIVE工作请求,将RECEIVE工作请求发送给Rsockets协议。当工作请求模块从获取工作请求函数接收到“获取工作请求”时,创建工作请求结构体数组,向rsend函数或rsendto函数发送创建的工作请求结构体数组地址和数组的长度。当工作请求模块从请求RDMA资源函数接收到“RDMA资源请求”时,判断工作请求模块是否获取到了RDMA资源,如果没有获取到RDMA资源,则向Rsockets协议发送“RDMA资源请求”以获取RDMA资源。
第二步,发送端和接收端的套接字应用向Rsockets协议发送socket请求,创建RDMA资源。内存管理模块和内存处理模块相互配合创建缓存池,建立对缓存池的内存映射,方法是:
2.1发送端和接收端套接字应用调用Linux系统的socket函数,使用Rsockets协议拦截socket函数,采用Rsockets协议中的rsocket函数替代socket函数,rsocket函数调用请求创建缓存池函数,请求创建内存池函数向内存管理模块发送“创建缓存池请求”。
2.2内存管理模块收到rsocket函数的“创建缓存池请求”,打开内存处理模块的字符设备,向内存处理模块的字符设备传递“创建缓存池请求”。
2.3内存处理模块的字符设备收到“创建缓存池请求”后,创建一个物理地址连续,大小为16MB的内存块作为缓存池,如果创建失败则显示“创建缓存池失败”,转3.32,如果创建成功,则向内存管理模块返回缓存池的物理地址和长度,转2.4。
2.4内存管理模块初始化内存管理结构体,内存管理结构体的内容包含缓存池物理地址首地址、缓存池虚拟地址首地址、长度、空闲长度、数据头指针、数据尾指针,内存管理模块将从字符设备接收的缓存池的物理地址和长度分别存入到内存管理结构体的缓存池物理地址首地址和长度中。而内存管理结构体的空闲长度初始化为内存管理结构体的长度,内存管理结构体的数据头指针初始化为零,内存管理结构体的数据尾指针初始化为零。
2.5内存管理模块构造“内存映射请求”,向内存处理模块的字符设备发送“内存映射请求”,请求映射缓存池物理地址。
2.6字符设备收到“建立内存映射请求”后,根据缓存池物理地址建立内存映射,调用Linux内核的remap_pfn_range函数将缓存池的物理地址与Linux内核查找的虚拟地址建立内存映射,将与缓存池的物理地址对应的Linux内核查找的虚拟地址返回给内存管理模块,内存管理模块将虚拟地址首地址写入内存管理结构体的缓存池虚拟地址首地址。
2.7 Rsockets协议的rsocket函数根据从发送端和接收端套接字应用调用的socket函数传入的参数type和protocol来确认是TCP还是UDP传输,如果是TCP传输,转2.7.1。如果是UDP传输,转2.7.2。
2.7.1如果是从发送端获取的type和protocol,说明是发送端套接字应用,由于是TCP传输的发送端套接字应用,需要调用Linux系统的connect函数建立连接,转2.8。如果是从接收端获取的type和protocol,说明是接收端套接字应用,由于是TCP传输的接收端套接字应用,需要调用Linux系统的accept函数接收发送端套接字应用的连接请求,转2.11。
2.7.2如果是从发送端获取的type和protocol,说明是发送端套接字应用,由于是UDP传输的发送端套接字应用,不需要建立连接,需要调用Linux系统的sendto函数发送消息,转3.16。如果是从发送端获取的type和protocol,说明是接收端套接字应用,由于是UDP传输的接收端套接字应用,需要调用Linux系统的bind函数绑定IP地址,转2.14。
2.8发送端套接字应用调用Linux系统的connect函数,使用Rsockets协议拦截connect函数,采用Rsockets协议的rconnect函数替代connect函数。rconnect函数调用交换缓存池地址函数,交换缓存池地址函数向发送端的内存管理模块发送“交换缓存池请求”。
2.9发送端的内存管理模块从rconnect函数接收“交换缓存池请求”,内存管理模块将发送端的内存管理结构体(命名为A1)的内容发送给接收端的内存管理模块,并等待接收端返回接收端的内存管理结构体(命名为A2),若发送端内存管理模块接收到A2,将A2存入到发送端的第二内存管理结构体(命名为B1)中,B1的内容包含接收端缓存池的物理地址首地址,接收端缓存池虚拟地址首地址,长度,空闲长度,数据头指针,数据尾指针。
2.10 Rsockets协议的rconnect函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域。转第三步。
2.11接收端套接字应用调用Linux系统的accept函数,使用Rsockets协议拦截accept函数,采用Rsockets协议的raccept函数替代accept函数。raccept函数调用交换缓存池地址函数,交换缓存池地址函数向接收端的内存管理模块发送“交换缓存池请求”。
2.12接收端的内存管理模块从raccept函数接收的“交换缓存池请求”,内存管理模块从发送端内存管理模块接收A1,将A1存入到接收端的第二内存管理结构体(命名B2)中,B2的内容包含发送端缓存池物理地址首地址,发送端缓存池虚拟地址首地址,长度,空闲长度,数据头指针,数据尾指针。接收端的内存管理模块将A2发送给发送端内存管理模块。
2.13 raccept函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域。转3.30。
2.14接收端套接字应用调用bind函数,使用Rsockets协议拦截bind函数,采用Rsockets协议的rbind函数替代bind函数,rbind函数调用请求接收工作请求函数,请求接收工作请求函数向工作请求模块发送Rsockets协议的rconnect函数创建的RDMA资源和“构造接收工作请求”。
2.15工作请求模块从rbind函数接收“构造接收工作请求”和RDMA资源,构造RECEIVE工作请求,设置目的地址为内存管理结构体(命名为A3)的缓存池虚拟地址,接收长度为2MB,共设置8个RECEIVE工作请求,第一个工作请求的目的地址为A3的发送端缓存池虚拟地址首地址,后面每个工作请求的目的地址依次增长2MB。工作请求模块调用OFED库的ibv_post_recv函数,将所有的RECEIVE工作请求发布到网卡中。转3.31。
第三步,发送端套接字应用从其发送缓存发送数据,内存管理模块和内存处理模块处理发送缓存后得到物理地址和页个数,工作请求模块构造对应工作请求,交由RDMA网卡执行工作请求将数据发送到接收端的缓存池中,接收端的内存管理模块将接收端套接字应用的接收缓存与缓存池中数据的物理地址建立内存映射,直接拿取数据。数据成功到达接收端套接字应用。方法是:
3.1发送端套接字应用调用write或send函数发送数据,使用Rsockets协议拦截write或send函数,采用Rsockets协议的rsend函数替代write或send函数,rsend函数调用请求内存处理函数,请求内存处理函数向发送端的内存管理模块发送“内存处理请求”,“内存处理请求”包含所在套接字应用发送缓存虚拟地址首地址,发送缓存的长度。
3.2发送端内存管理模块收到“内存处理请求”和内存地址信息,内存管理模块将内存地址信息处理为“内存处理请求”,向发送端的内存处理模块的系统调用处理模块传递“内存处理请求”。
3.3发送端的系统调用处理模块收到“内存处理请求”,从“内存处理请求”中获取到套接字应用发送缓存的虚拟地址和长度,调用Linux内核的get_user_pages函数处理套接字应用的发送缓存虚拟地址和发送缓存长度,得到发送端套接字发送缓存对应的物理地址和页个数,设置每个页不可交换,并且每个页是只读,使用链表存储物理地址,将存储物理地址的链表和页个数返回给发送端的内存管理模块。
3.4发送端的内存管理模块收到发送端的内存处理模块返回的存储物理地址的链表和页个数,使用地址管理结构体的物理地址链表头指针存储包含物理地址的链表的地址,地址管理结构体的页个数存储从内存处理模块返回的页个数,地址管理结构体包含物理地址链表头指针、页个数。
3.5 rsend函数调用请求RDMA资源函数,请求RDMA资源函数向发送端的工作请求模块发送“RDMA资源请求”。
3.6发送端的工作请求模块收到“RDMA资源请求”,工作请求模块判断是否已经获取RDMA资源,如果没有获取RDMA资源,向请求RDMA资源函数返回“RDMA资源请求”,请求RDMA资源函数收到“RDMA资源请求”后向发送端的工作请求模块发送RDMA资源,发送端的工作请求模块获取RDMA资源,转3.7。如果已经获取RDMA资源,则直接转3.7。
3.7发送端的工作请求模块从发送端的内存管理模块获取地址管理结构体和内存管理结构体B1,构造操作类型为WRITE的工作请求结构体,如果地址管理结构体的物理地址是连续的,转3.8。如果地址管理结构体的物理地址是离散的,转3.9。
3.8发送端的工作请求模块构造一个WRITE工作请求结构体数组,元素个数为1。设置工作请求结构体元素的源地址为地址管理结构体中的第一个物理地址,工作请求结构体元素的发送长度为地址管理结构体的页个数与Linux系统的页大小之积。转3.10
3.9发送端的工作请求模块构造一个WRITE工作请求结构体数组,数组元素个数为地址管理结构体的页个数。依次将地址管理结构体的链表的物理地址写入到工作请求结构体数组元素的源地址中,工作请求结构体数组的每个元素的发送长度为Linux系统页的大小。转3.10。
3.10 rsend函数调用获取工作请求函数,获取工作请求函数向发送端的工作请求模块发送“获取工作请求”。
3.11发送端的工作请求模块获取“获取工作请求”后,向rsend函数返回工作请求结构体数组的地址和数组元素个数。rsend函数接收工作请求结构体数组地址和数组长度。
3.12 rsend函数调用判断缓存池函数,向发送端的内存管理模块发送“判断缓存池长度请求”。
3.13发送端的内存管理模块收到“判断缓存池长度请求”后,判断B1的空闲长度是否大于套接字应用的发送缓存的长度,如果B1的空闲长度小于套接字应用的发送缓存的长度,将B1的空闲长度返回给rsend函数,如果B1的空闲长度大于或等于套接字应用的发送缓存的长度,将套接字应用的发送缓存的长度返回给rsend函数。
3.14 rsend函数接收到3.13返回的长度,记为rsend函数的可发送长度,调用WRITE发送管理函数。
3.15 WRITE发送管理函数从rsend函数获取工作请求结构体数组的地址、数组元素个数、可发送长度,对获取的工作请求结构体数组,调用OFED库的ibv_post_send函数进行处理,具体方法如下:
3.15.1 WRITE发送管理函数从工作请求结构体数组取出元素,设置工作请求结构体数组元素的目的地址为B1的接收端缓存区的虚拟地址首地址,判断工作请求结构体数组元素的发送长度是否大于可发送长度,如果大于,转3.12。如果小于等于可发送长度,转3.15.2。
3.15.2 WRITE发送管理函数调用OFED库的ibv_post_send函数将取出的工作请求结构体元素发送到RDMA网卡。RDMA网卡从工作请求结构体数组元素的源地址读取数据,并发送到工作请求结构体数组元素的目的地址指定位置中,RDMA网卡发送数据的长度为工作请求结构体元素的发送长度。
3.15.3 WRITE发送管理函数将可发送长度减去工作请求结构体元素的发送长度,将B1的接收端缓存区虚拟地址首地址加上工作请求结构体元素的发送长度后存入B1的接收端缓存区虚拟地址首地址。转3.15.4。
3.15.4 WRITE发送管理函数判断工作请求结构体数组元素是否为空,如果为空,转3.32,如果不为空,转3.15.1。
3.16发送端套接字应用调用Linux系统的sendto函数,使用Rsockets协议拦截sendto函数,采用Rsockets协议的rsendto函数替代sendto函数,rsendto函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域,rsendto函数调用请求内存处理函数,请求内存处理函数向发送端的内存管理模块发送“内存处理请求”,“内存处理请求”包含所在套接字应用发送缓存虚拟地址首地址,发送缓存的长度。
3.17发送端的内存管理模块收到“内存处理请求”,向发送端的内存处理模块的系统调用处理模块传递“内存处理请求”。
3.18发送端的系统调用处理模块接收“内存处理请求”,系统调用处理模块从“内存处理请求”中获取到套接字应用发送缓存的虚拟地址和长度,系统调用处理模块处理套接字应用的发送缓存虚拟地址和发送缓存长度,得到对应的物理地址和页个数,设置每个页不可交换,并且设置每个页是只读,使用链表存储物理地址,将存储物理地址的链表和页个数返回给发送端的内存管理模块。
3.20发送端的内存管理模块收到发送端的内存处理模块返回的存储物理地址的链表和页个数,使用地址管理结构体的物理地址链表头指针存储包含物理地址的链表的地址,地址管理结构体的页个数存储从内存处理模块返回的页个数,地址管理结构体包含物理地址链表头指针,页个数。
3.21 rsendto函数调用请求RDMA资源函数,请求RDMA资源函数向发送端的工作请求模块发送“RDMA资源请求”。
3.22发送端的工作请求模块接收到“RDMA资源请求”,判断是否已经获取RDMA资源,如果没有获取RDMA资源,向请求RDMA资源函数返回“RDMA资源请求”,请求RDMA资源函数收到“RDMA资源请求”,向发送端的工作请求模块发送Rsockets协议的rsendto函数创建的RDMA资源,发送端的工作请求模块获取RDMA资源,转3.23。如果已经获取RDMA资源,直接转3.23。
3.23发送端的工作请求模块从发送端的内存管理模块获取地址管理结构体,构造操作类型为SEND的工作请求结构体,如果地址管理结构体的物理地址是连续的,转3.24。如果地址管理结构体的物理地址是离散的,转3.25。
3.24发送端的工作请求模块构造一个SEND工作请求结构体数组,元素个数为1。设置工作请求结构体数组元素的源地址为地址管理结构体中的第一个物理地址,工作请求结构体数组元素的发送长度为地址管理结构体的页个数与Linux系统的页大小之积。转3.26。
3.25工作请求模块构造一个SEND工作请求结构体数组,元素个数为地址管理结构体的页个数。依次将地址管理结构体的链表的物理地址写入到工作请求结构体数组的元素的源地址中,工作请求结构体数组的每个元素的发送长度为Linux系统页的大小。转3.26。
3.26 rsendto函数调用获取工作请求函数,获取工作请求函数向发送端的工作请求模块发送“获取工作请求”。
3.27发送端的工作请求模块获取“获取工作请求”,将工作请求结构体数组的地址和元素个数给返回给rsendto函数。
3.28rsendto函数接收工作请求结构体数组地址和数组长度,rsendto函数调用SEND发送管理函数。
3.29 SEND发送管理函数从rsendto函数获取工作请求结构体数组的地址、数组长度,对获的工作请求结构体数组,进行如下处理:
3.29.1 SEND发送管理函数取出工作请求结构体数组元素。
3.29.2 SEND发送管理函数调用OFED库的ibv_post_send函数,将取出的工作请求结构体数组元素发送到RDMA网卡。RDMA网卡从工作请求结构体元素的源地址读取数据,将数据发送到接收端的RDMA网卡,接收端的RDMA网卡将发送端的数据放置到RECEIVE工作请求指定的位置中。
3.29.3 SEND发送管理函数判断工作请求结构体数组元素是否为空,如果为空,转3.32,如果不为空,转3.29.1。
3.30接收端套接字应用调用Linux系统的recv或者read函数接收数据,使用Rsockets协议拦截recv或read函数,采用Rsockets协议的rrecv函数替代recv或者read函数,rrecv函数调用WRITE处理完成事件函数,具体方法为:
3.30.1 WRITE处理完成事件函数调用OFED库提供的ibv_poll_cq函数获取完成事件,如果获取到完成事件,解析完成事件获取数据的长度,将内存管理结构体A2的数据尾指针的长度增加数据的长度,A2的数据头指针指向数据所在首地址,转3.30.2。如果没有获取到完成事件,则显示“获取完成失败,没有数据到达”,转3.32。
3.30.2 WRITE处理完成事件函数判断接收端套接字应用调用rrecv函数传入的长度是否大于3.30.1获取的数据长度,如果大于3.30.1获取的数据长度,记接收长度为数据长度,否则记接收长度为接收端套接字应用调用rrecv函数传入的长度。如果接收长度大于16KB,转3.30.3,如果接收长度小于或等于16KB,转3.30.5。
3.30.3 WRITE处理完成事件函数向接收端的内存管理模块发送“内存映射请求”。接收端的内存管理模块收到“内存映射请求”,处理为“建立内存映射请求”,向接收端的内存处理模块的字符设备传递“建立内存映射请求”。
3.30.4接收端的内存处理模块的字符设备收到“建立内存映射请求”,从“建立内存映射请求”中获取虚拟地址和物理地址、数据的长度,建立虚拟地址到物理地址的内存映射。转3.30.6。
3.30.5 WRITE处理完成事件函数将数据从数据所在地址拷贝到接收端套接字应用的接收缓存中。转3.30.6。
3.30.6 WRITE处理完成事件函数将A2的空闲长度增加接收的长度,A2的数据头指针增加接收长度的值,套接字应用的接收缓存的长度减去接收的长度,WRITE处理完成事件函数将A2的内容写到发送端的B1中。
3.30.7 WRITE处理完成事件函数判断套接字应用的接收缓存长度是否为零,如果为零,转3.32,如果不为零,转3.30.1。
3.31接收端套接字应用调用recvfrom函数,使用Rsockets协议拦截recvfrom函数,采用Rsockets协议的rrecvfrom函数替代recvfrom函数,rrecvfrom函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域,rrecvfrom函数调用SEND处理完成事件函数,具体方法为:
3.31.1 SEND处理完成事件函数调用OFED库提供的ibv_poll_cq函数获取完成事件,如果获取到完成事件,解析完成事件获取数据的长度,将内存管理结构体A2的数据尾指针的长度增加数据的长度,A2的数据头指针指向数据所在首地址,转3.31.2。如果没有获取到完成事件,则显示“获取完成事件失败,数据未到达”,转3.32。
3.31.2 SEND处理完成事件函数判断接收端套接字应用调用rrecv函数传入的长度是否大于3.31.1获取的数据长度,如果大于,记接收长度为数据长度,否则接收长度为接收端套接字应用调用rrecv函数传入的长度。如果接收长度大于16KB,转3.31.3,如果接收长度小于或等于16KB,转3.31.5。
3.31.3 SEND处理完成事件函数向接收端的内存管理模块发送“内存映射请求”。接收端的内存管理模块收到“内存映射请求”,处理为“建立内存映射请求”,向接收端的内存处理模块的字符设备传递“建立内存映射请求”。
3.31.4接收端的内存处理模块的字符设备收到“建立内存映射请求”,从“建立内存映射请求”中获取虚拟地址和物理地址,数据的长度,调用Linux内核的remap_pfn_range函数建立虚拟地址到物理地址的内存映射。转3.31.6。
3.31.5 SEND处理完成事件函数将数据从数据所在地址拷贝到接收端的套接字应用的接收缓存中。转3.31.6。
3.31.6 SEND处理完成事件函数将A2的空闲长度增加接收的长度,A2的数据头指针增加接收长度的值,套接字应用的接收缓存的长度减去接收的长度。转3.31.7。
3.31.7 SEND处理完成事件函数构造RECEIVE工作请求,工作请求的目的地址为A2的数据尾指针指向的地址,工作请求的长度为接收的长度,调用OFED库的ibv_poll_cq函数将RECEIVE工作请求发布到RDMA网卡中。转3.31.8。
3.31.8 SEND处理完成事件函数判断套接字应用的接收缓存长度是否为零,如果为零,转3.32,如果不为零,转3.31.1。
3.32结束。

Claims (3)

1.一种基于Rsockets协议的零拷贝数据传输方法,其特征在于包含以下步骤:
第一步,构建基于Rsockets协议的零拷贝数据传输系统;基于Rsockets协议的零拷贝数据传输系统由基于Rsockets协议的RDMA传输系统,内存管理模块,内存处理模块,工作请求模块组成;基于Rsockets协议的RDMA传输系统包括套接字应用,OFED库,OFED内核库以及RDMA网卡;发送端和接收端都安装有基于Rsockets协议的零拷贝数据传输系统;
基于Rsockets协议的RDMA传输系统中,套接字应用和OFED库安装在用户空间,Rsockets协议属于OFED库的一部分,OFED内核库安装在内核空间,RDMA网卡为硬件,安装在主机的PCIE插槽内;
修改Rsockets协议中的相关函数:在Rsockets协议中添加SEND发送管理函数,在Rsockets协议的rsendto函数中增加调用SEND发送管理函数的功能,SEND发送管理函数负责发送工作请求模块构造的SEND工作请求;在Rsockets协议中添加WRITE发送管理函数,在Rsockets协议的rsend函数增加调用WRITE发送管理函数的功能,WRITE发送管理函数负责发送工作请求模块构造的WRITE工作请求;Rsockets协议的rconnect函数、raccept函数、rsendto函数,rrecvfrom函数增加调用OFED库的注册物理地址内存区域函数的功能,使得具有注册物理地址内存区域的功能;在Rsockets协议中增加请求创建缓存池函数,在Rsockets协议增加调用请求创建缓存池函数的功能,请求创建缓存池函数向内存管理模块发送“创建缓存池请求”;在Rsockets协议中增加请求内存处理函数,在rsend函数和rsendto函数中增加调用请求内存处理函数的功能,请求内存处理函数向内存管理模块发送“内存处理请求”和内存地址信息;在Rsockets协议中增加请求RDMA资源函数,在rsend函数和rsendto函数增加调用请求RDMA资源函数的功能,请求RDMA资源函数向工作请求模块发送“RDMA资源请求”;在Rsockets协议中增加判断缓存池函数,在rsend函数中增加调用判断缓存池函数的功能,向内存管理模块发送“判断缓存池长度请求”;在Rsockets协议中增加WRITE处理完成事件函数,在rrecv函数增加调用WRITE处理完成事件函数的功能,负责处理WRITE工作请求的消息的接收,并向内存管理模块发送“内存映射请求”;在Rsockets协议中增加SEND处理完成事件函数,在rrecvfrom函数增加调用SEND处理完成事件函数的功能,负责处理SEND工作请求的消息的接收,SEND处理完成事件函数向内存管理模块发送“内存映射请求”;在Rsockets协议中增加请求接收工作请求函数,在rbind函数增加调用请求接收工作请求函数的功能,请求接收工作请求函数向工作请求模块发送RDMA资源和“构造接收工作请求”;在Rsockets协议增加获取工作请求函数,在rsend函数和rsendto函数增加调用获取工作请求函数的功能,获取工作请求函数向工作请求模块发送“获取工作请求”;
内存管理模块运行在用户空间,与工作请求模块,内存处理模块以及OFED库的Rsockets协议相连,负责管理套接字应用的发送缓存和接收缓存以及缓存池;缓存池仅用于存储接收的数据,并提供数据所在的物理地址使得套接字应用的接收缓存可以与消息所在的物理地址建立内存映射,直接获取数据;当内存管理模块从请求创建缓存池函数接收到“创建缓存池请求”时,向内存处理模块发送“创建缓存池请求”,并从内存处理模块接收缓存池的物理地址,当内存管理模块接收到缓存池的物理地址,向内存管理模块发送“建立内存映射请求”,并从内存处理模块接收缓存池的虚拟地址;当内存管理模块从交换缓存池地址函数接收到“交换缓存池请求”时,发送端内存管理模块和接受端内存管理模块互相交换缓存池地址信息;当内存管理模块从请求内存处理函数接收到“内存处理请求”时,向内存处理模块发送“内存处理请求”,并从内存处理模块接收到物理地址和页个数,向工作请求模块返回物理地址和页个数;当内存管理模块从判断缓存池函数接收到“判断缓存池长度请求”时,内存管理模块计算缓存池长度,将缓存池长度返回给rsend函数;内存管理模块从WRITE处理完成事件函数接收到“内存映射请求”时,向内存处理模块发送“建立内存映射请求”,并从内存处理模块接收到套接字应用的发送缓存的虚拟地址;当内存管理模块从SEND处理完成事件函数接收到“内存映射请求”时,向内存处理模块发送“建立内存映射请求”,并从内存处理模块接收到套接字应用的发送缓存的虚拟地址;
内存处理模块运行在Linux系统的内核空间,与内存管理模块相连接,由两个部分组成,一个是提供内存处理功能的系统调用处理模块,一个是提供创建缓存池和内存映射功能的字符设备;系统调用处理模块负责处理从内存管理模块接收的“内存处理请求”,向内存管理模块发送物理地址和页个数;字符设备负责处理从内存管理模块接收的“创建缓存池请求”,创建一个缓存池,向内存管理模块返回缓存池的物理地址;字符设备处理从内存管理模块接收“建立内存映射请求”,建立内存映射,向内存管理模块传递与缓存池的物理地址对应的虚拟地址;
工作请求模块运行在用户空间,与内存管理模块和Rsockets协议相连接,负责构造对应的工作请求,将工作请求交由Rsockets协议处理;工作请求模块从Rsockets协议中获取RDMA资源,从内存管理模块获取内存的物理地址和页个数,构造基于物理地址发送的工作请求,并将基于物理地址发送的工作请求发送给Rsockets协议;当工作请求模块从请求接收工作请求函数收到RDMA资源和“构造接收工作请求”时,创建RECEIVE工作请求,将RECEIVE工作请求发送给Rsockets协议;当工作请求模块从获取工作请求函数接收到“获取工作请求”时,创建工作请求结构体数组,向rsend函数或rsendto函数发送创建的工作请求结构体数组地址和数组的长度;当工作请求模块从请求RDMA资源函数接收到“RDMA资源请求”时,判断工作请求模块是否获取到了RDMA资源,如果没有获取到RDMA资源,则向Rsockets协议发送“RDMA资源请求”以获取RDMA资源;
第二步,发送端和接收端的套接字应用向Rsockets协议发送socket请求,创建RDMA资源;内存管理模块和内存处理模块相互配合创建缓存池,建立对缓存池的内存映射,方法是:
2.1发送端和接收端套接字应用调用Linux系统的socket函数,使用Rsockets协议拦截socket函数,采用Rsockets协议中的rsocket函数替代socket函数,rsocket函数调用请求创建缓存池函数,请求创建内存池函数向内存管理模块发送“创建缓存池请求”;
2.2内存管理模块收到rsocket函数的“创建缓存池请求”,打开内存处理模块的字符设备,向内存处理模块的字符设备传递“创建缓存池请求”;
2.3内存处理模块的字符设备收到“创建缓存池请求”后,创建一个物理地址连续的内存块作为缓存池,如果创建失败则显示“创建缓存池失败”,转3.32,如果创建成功,则向内存管理模块返回缓存池的物理地址和长度,转2.4;
2.4内存管理模块初始化内存管理结构体,内存管理结构体的内容包含缓存池物理地址首地址、缓存池虚拟地址首地址、长度、空闲长度、数据头指针、数据尾指针,内存管理模块将从字符设备接收的缓存池的物理地址和长度分别存入到内存管理结构体的缓存池物理地址首地址和长度中;内存管理结构体的空闲长度初始化为内存管理结构体的长度,内存管理结构体的数据头指针初始化为零,内存管理结构体的数据尾指针初始化为零;
2.5内存管理模块构造“内存映射请求”,向内存处理模块的字符设备发送“内存映射请求”,请求映射缓存池物理地址;
2.6字符设备收到“建立内存映射请求”后,根据缓存池物理地址建立内存映射,调用Linux内核的remap_pfn_range函数将缓存池的物理地址与Linux内核查找的虚拟地址建立内存映射,将与缓存池的物理地址对应的Linux内核查找的虚拟地址返回给内存管理模块,内存管理模块将虚拟地址首地址写入内存管理结构体的缓存池虚拟地址首地址;
2.7Rsockets协议的rsocket函数根据从发送端和接收端套接字应用调用的socket函数传入的参数type和protocol来确认是TCP还是UDP传输,如果是TCP传输,转2.7.1;如果是UDP传输,转2.7.2;
2.7.1如果是从发送端获取的type和protocol,说明是发送端套接字应用,转2.8;如果是从接收端获取的type和protocol,说明是接收端套接字应用,转2.11;
2.7.2如果是从发送端获取的type和protocol,说明是发送端套接字应用,转3.16;如果是从发送端获取的type和protocol,说明是接收端套接字应用,转2.14;
2.8发送端套接字应用调用Linux系统的connect函数,使用Rsockets协议拦截connect函数,采用Rsockets协议的rconnect函数替代connect函数;rconnect函数调用交换缓存池地址函数,交换缓存池地址函数向发送端的内存管理模块发送“交换缓存池请求”;
2.9发送端的内存管理模块从rconnect函数接收“交换缓存池请求”,内存管理模块将发送端的内存管理结构体A1的内容发送给接收端的内存管理模块,并等待接收端返回接收端的内存管理结构体A2,若发送端内存管理模块接收到A2,将A2存入到发送端的第二内存管理结构体B1中,B1的内容包含接收端缓存池的物理地址首地址,接收端缓存池虚拟地址首地址,长度,空闲长度,数据头指针,数据尾指针;
2.10Rsockets协议的rconnect函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域;转第三步;
2.11接收端套接字应用调用Linux系统的accept函数,使用Rsockets协议拦截accept函数,采用Rsockets协议的raccept函数替代accept函数;raccept函数调用交换缓存池地址函数,交换缓存池地址函数向接收端的内存管理模块发送“交换缓存池请求”;
2.12接收端的内存管理模块从raccept函数接收的“交换缓存池请求”,内存管理模块从发送端内存管理模块接收A1,将A1存入到接收端的第二内存管理结构体B2中,B2的内容包含发送端缓存池物理地址首地址,发送端缓存池虚拟地址首地址,长度,空闲长度,数据头指针,数据尾指针;接收端的内存管理模块将A2发送给发送端内存管理模块;
2.13raccept函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域;转3.30;
2.14接收端套接字应用调用bind函数,使用Rsockets协议拦截bind函数,采用Rsockets协议的rbind函数替代bind函数,rbind函数调用请求接收工作请求函数,请求接收工作请求函数向工作请求模块发送Rsockets协议的rconnect函数创建的RDMA资源和“构造接收工作请求”;
2.15工作请求模块从rbind函数接收“构造接收工作请求”和RDMA资源,构造RECEIVE工作请求,并调用OFED库的ibv_post_recv函数,将所有RECEIVE工作请求发布到网卡中;转3.31;
第三步,发送端套接字应用从其发送缓存发送数据,内存管理模块和内存处理模块处理发送缓存后得到物理地址和页个数,工作请求模块构造对应工作请求,交由RDMA网卡执行工作请求将数据发送到接收端的缓存池中,接收端的内存管理模块将接收端套接字应用的接收缓存与缓存池中数据的物理地址建立内存映射,直接拿取数据;数据成功到达接收端套接字应用;方法是:
3.1发送端套接字应用调用write或send函数发送数据,使用Rsockets协议拦截write或send函数,采用Rsockets协议的rsend函数替代write或send函数,rsend函数调用请求内存处理函数,请求内存处理函数向发送端的内存管理模块发送“内存处理请求”,“内存处理请求”包含所在套接字应用发送缓存虚拟地址首地址,发送缓存的长度;
3.2发送端内存管理模块收到“内存处理请求”和内存地址信息,内存管理模块将内存地址信息处理为“内存处理请求”,向发送端的内存处理模块的系统调用处理模块传递“内存处理请求”;
3.3发送端的系统调用处理模块收到“内存处理请求”,从“内存处理请求”中获取到套接字应用发送缓存的虚拟地址和长度,调用Linux内核的get_user_pages函数处理套接字应用的发送缓存虚拟地址和发送缓存长度,得到发送端套接字发送缓存对应的物理地址和页个数,设置每个页不可交换,并且每个页是只读,使用链表存储物理地址,将存储物理地址的链表和页个数返回给发送端的内存管理模块;
3.4发送端的内存管理模块收到发送端的内存处理模块返回的存储物理地址的链表和页个数,使用地址管理结构体的物理地址链表头指针存储包含物理地址的链表的地址,地址管理结构体的页个数存储从内存处理模块返回的页个数,地址管理结构体包含物理地址链表头指针、页个数;
3.5rsend函数调用请求RDMA资源函数,请求RDMA资源函数向发送端的工作请求模块发送“RDMA资源请求”;
3.6发送端的工作请求模块收到“RDMA资源请求”,工作请求模块判断是否已经获取RDMA资源,如果没有获取RDMA资源,向请求RDMA资源函数返回“RDMA资源请求”,请求RDMA资源函数收到“RDMA资源请求”后向发送端的工作请求模块发送RDMA资源,发送端的工作请求模块获取RDMA资源,转3.7;如果已经获取RDMA资源,则直接转3.7;
3.7发送端的工作请求模块从发送端的内存管理模块获取地址管理结构体和内存管理结构体B1,构造操作类型为WRITE的工作请求结构体,如果地址管理结构体的物理地址是连续的,转3.8;如果地址管理结构体的物理地址是离散的,转3.9;
3.8发送端的工作请求模块构造一个WRITE工作请求结构体数组,元素个数为1;设置工作请求结构体元素的源地址为地址管理结构体中的第一个物理地址,工作请求结构体元素的发送长度为地址管理结构体的页个数与Linux系统的页大小之积;转3.10
3.9发送端的工作请求模块构造一个WRITE工作请求结构体数组,数组元素个数为地址管理结构体的页个数;依次将地址管理结构体的链表的物理地址写入到工作请求结构体数组元素的源地址中,工作请求结构体数组的每个元素的发送长度为Linux系统页的大小;转3.10;
3.10rsend函数调用获取工作请求函数,获取工作请求函数向发送端的工作请求模块发送“获取工作请求”;
3.11发送端的工作请求模块获取“获取工作请求”后,向rsend函数返回工作请求结构体数组的地址和数组元素个数;rsend函数接收工作请求结构体数组地址和数组长度;
3.12rsend函数调用判断缓存池函数,向发送端的内存管理模块发送“判断缓存池长度请求”;
3.13发送端的内存管理模块收到“判断缓存池长度请求”后,判断B1的空闲长度是否大于套接字应用的发送缓存的长度,如果B1的空闲长度小于套接字应用的发送缓存的长度,将B1的空闲长度返回给rsend函数,如果B1的空闲长度大于或等于套接字应用的发送缓存的长度,将套接字应用的发送缓存的长度返回给rsend函数;
3.14rsend函数接收到3.13返回的长度,记为rsend函数的可发送长度;调用WRITE发送管理函数;
3.15WRITE发送管理函数从rsend函数获取工作请求结构体数组的地址、数组元素个数、可发送长度;对获取的工作请求结构体数组,调用OFED库的ibv_post_send函数进行处理,具体方法如下:
3.15.1WRITE发送管理函数从工作请求结构体数组取出元素,设置工作请求结构体数组元素的目的地址为B1的接收端缓存区的虚拟地址首地址,判断工作请求结构体数组元素的发送长度是否大于可发送长度,如果大于,转3.12;如果小于等于可发送长度,转3.15.2;
3.15.2WRITE发送管理函数调用OFED库的ibv_post_send函数将取出的工作请求结构体元素发送到RDMA网卡;RDMA网卡从工作请求结构体数组元素的源地址读取数据,并发送到工作请求结构体数组元素的目的地址指定位置中,RDMA网卡发送数据的长度为工作请求结构体元素的发送长度;
3.15.3WRITE发送管理函数将可发送长度减去工作请求结构体元素的发送长度,将B1的接收端缓存区虚拟地址首地址加上工作请求结构体元素的发送长度后存入B1的接收端缓存区虚拟地址首地址;转3.15.4;
3.15.4WRITE发送管理函数判断工作请求结构体数组元素是否为空,如果为空,转3.32,如果不为空,转3.15.1;
3.16发送端套接字应用调用Linux系统的sendto函数,使用Rsockets协议拦截sendto函数,采用Rsockets协议的rsendto函数替代sendto函数,rsendto函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域,rsendto函数调用请求内存处理函数,请求内存处理函数向发送端的内存管理模块发送“内存处理请求”,“内存处理请求”包含所在套接字应用发送缓存虚拟地址首地址,发送缓存的长度;
3.17发送端的内存管理模块收到“内存处理请求”,向发送端的内存处理模块的系统调用处理模块传递“内存处理请求”;
3.18发送端的系统调用处理模块接收“内存处理请求”,系统调用处理模块从“内存处理请求”中获取到套接字应用发送缓存的虚拟地址和长度,系统调用处理模块处理套接字应用的发送缓存虚拟地址和发送缓存长度,得到对应的物理地址和页个数,设置每个页不可交换,并且设置每个页是只读,使用链表存储物理地址,将存储物理地址的链表和页个数返回给发送端的内存管理模块;
3.20发送端的内存管理模块收到发送端的内存处理模块返回的存储物理地址的链表和页个数,使用地址管理结构体的物理地址链表头指针存储包含物理地址的链表的地址,地址管理结构体的页个数存储从内存处理模块返回的页个数,地址管理结构体包含物理地址链表头指针,页个数;
3.21rsendto函数调用请求RDMA资源函数,请求RDMA资源函数向发送端的工作请求模块发送“RDMA资源请求”;
3.22发送端的工作请求模块接收到“RDMA资源请求”,判断是否已经获取RDMA资源,如果没有获取RDMA资源,向请求RDMA资源函数返回“RDMA资源请求”,请求RDMA资源函数收到“RDMA资源请求”,向发送端的工作请求模块发送Rsockets协议的rsendto函数创建的RDMA资源,发送端的工作请求模块获取RDMA资源,转3.23;如果已经获取RDMA资源,直接转3.23;
3.23发送端的工作请求模块从发送端的内存管理模块获取地址管理结构体,构造操作类型为SEND的工作请求结构体,如果地址管理结构体的物理地址是连续的,转3.24;如果地址管理结构体的物理地址是离散的,转3.25;
3.24发送端的工作请求模块构造一个SEND工作请求结构体数组,元素个数为1;设置工作请求结构体数组元素的源地址为地址管理结构体中的第一个物理地址,工作请求结构体数组元素的发送长度为地址管理结构体的页个数与Linux系统的页大小之积;转3.26;
3.25工作请求模块构造一个SEND工作请求结构体数组,元素个数为地址管理结构体的页个数;依次将地址管理结构体的链表的物理地址写入到工作请求结构体数组的元素的源地址中,工作请求结构体数组的每个元素的发送长度为Linux系统页的大小;转3.26;
3.26rsendto函数调用获取工作请求函数,获取工作请求函数向发送端的工作请求模块发送“获取工作请求”;
3.27发送端的工作请求模块获取“获取工作请求”,将工作请求结构体数组的地址和元素个数给返回给rsendto函数;
3.28rsendto函数接收工作请求结构体数组地址和数组长度;rsendto函数调用SEND发送管理函数;
3.29SEND发送管理函数从rsendto函数获取工作请求结构体数组的地址、数组长度;对获得的工作请求结构体数组,进行如下处理:
3.29.1SEND发送管理函数取出工作请求结构体数组元素;
3.29.2SEND发送管理函数调用OFED库的ibv_post_send函数,将取出的工作请求结构体数组元素发送到RDMA网卡;RDMA网卡从工作请求结构体元素的源地址读取数据,将数据发送到接收端的RDMA网卡,接收端的RDMA网卡将发送端的数据放置到RECEIVE工作请求指定的位置中;
3.29.3SEND发送管理函数判断工作请求结构体数组元素是否为空,如果为空,转3.32,如果不为空,转3.29.1;
3.30接收端套接字应用调用Linux系统的recv或者read函数接收数据,使用Rsockets协议拦截recv或read函数,采用Rsockets协议的rrecv函数替代recv或者read函数,rrecv函数调用WRITE处理完成事件函数,具体方法为:
3.30.1WRITE处理完成事件函数调用OFED库提供的ibv_poll_cq函数获取完成事件,如果获取到完成事件,解析完成事件获取数据的长度,将内存管理结构体A2的数据尾指针的长度增加数据的长度,A2的数据头指针指向数据所在首地址,转3.30.2;如果没有获取到完成事件,则显示“获取完成失败,没有数据到达”,转3.32;
3.30.2WRITE处理完成事件函数判断接收端套接字应用调用rrecv函数传入的长度是否大于3.30.1获取的数据长度,如果大于3.30.1获取的数据长度,记接收长度为数据长度,否则记接收长度为接收端套接字应用调用rrecv函数传入的长度;如果接收长度大于16KB,转3.30.3,如果接收长度小于或等于16KB,转3.30.5;
3.30.3WRITE处理完成事件函数向接收端的内存管理模块发送“内存映射请求”;接收端的内存管理模块收到“内存映射请求”,处理为“建立内存映射请求”,向接收端的内存处理模块的字符设备传递“建立内存映射请求”;
3.30.4接收端的内存处理模块的字符设备收到“建立内存映射请求”,从“建立内存映射请求”中获取虚拟地址和物理地址、数据的长度,建立虚拟地址到物理地址的内存映射;转3.30.6;
3.30.5WRITE处理完成事件函数将数据从数据所在地址拷贝到接收端套接字应用的接收缓存中;转3.30.6;
3.30.6WRITE处理完成事件函数将A2的空闲长度增加接收的长度,A2的数据头指针增加接收长度的值,套接字应用的接收缓存的长度减去接收的长度,WRITE处理完成事件函数将A2的内容写到发送端的B1中;
3.30.7WRITE处理完成事件函数判断套接字应用的接收缓存长度是否为零,如果为零,转3.32,如果不为零,转3.30.1;
3.31接收端套接字应用调用recvfrom函数,使用Rsockets协议拦截recvfrom函数,采用Rsockets协议的rrecvfrom函数替代recvfrom函数,rrecvfrom函数调用OFED库的注册物理地址内存区域函数,注册物理地址内存区域,rrecvfrom函数调用SEND处理完成事件函数,具体方法为:
3.31.1SEND处理完成事件函数调用OFED库提供的ibv_poll_cq函数获取完成事件,如果获取到完成事件,解析完成事件获取数据的长度,将内存管理结构体A2的数据尾指针的长度增加数据的长度,A2的数据头指针指向数据所在首地址,转3.31.2;如果没有获取到完成事件,则显示“获取完成事件失败,数据未到达”,转3.32;
3.31.2SEND处理完成事件函数判断接收端套接字应用调用rrecv函数传入的长度是否大于3.31.1获取的数据长度,如果大于,记接收长度为数据长度,否则接收长度为接收端套接字应用调用rrecv函数传入的长度;如果接收长度大于16KB,转3.31.3,如果接收长度小于或等于16KB,转3.31.5;
3.31.3SEND处理完成事件函数向接收端的内存管理模块发送“内存映射请求”;接收端的内存管理模块收到“内存映射请求”,处理为“建立内存映射请求”,向接收端的内存处理模块的字符设备传递“建立内存映射请求”;
3.31.4接收端的内存处理模块的字符设备收到“建立内存映射请求”,从“建立内存映射请求”中获取虚拟地址和物理地址,数据的长度,调用Linux内核的remap_pfn_range函数建立虚拟地址到物理地址的内存映射;转3.31.6;
3.31.5SEND处理完成事件函数将数据从数据所在地址拷贝到接收端的套接字应用的接收缓存中;转3.31.6;
3.31.6SEND处理完成事件函数将A2的空闲长度增加接收的长度,A2的数据头指针增加接收长度的值,套接字应用的接收缓存的长度减去接收的长度;转3.31.7;
3.31.7SEND处理完成事件函数构造RECEIVE工作请求,工作请求的目的地址为A2的数据尾指针指向的地址,工作请求的长度为接收的长度,调用OFED库的ibv_poll_cq函数将RECEIVE工作请求发布到RDMA网卡中;转3.31.8;
3.31.8SEND处理完成事件函数判断套接字应用的接收缓存长度是否为零,如果为零,转3.32,如果不为零,转3.31.1;
3.32结束。
2.如权利要求1所述的基于Rsockets协议的零拷贝数据传输方法,其特征在于所述缓存池设置为16MB。
3.如权利要求1所述的基于Rsockets协议的零拷贝数据传输方法,其特征在于2.15步所述工作请求模块构造RECEIVE工作请求的方法是:设置目的地址为内存管理结构体A3的缓存池虚拟地址,接收长度为2MB,共设置8个RECEIVE工作请求,第一个工作请求的目的地址为A3的发送端缓存池虚拟地址首地址,后面每个工作请求的目的地址依次增长2MB。
CN202110399487.5A 2021-04-14 2021-04-14 基于Rsockets协议的零拷贝数据传输方法 Pending CN113064846A (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN202110399487.5A CN113064846A (zh) 2021-04-14 2021-04-14 基于Rsockets协议的零拷贝数据传输方法

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN202110399487.5A CN113064846A (zh) 2021-04-14 2021-04-14 基于Rsockets协议的零拷贝数据传输方法

Publications (1)

Publication Number Publication Date
CN113064846A true CN113064846A (zh) 2021-07-02

Family

ID=76566761

Family Applications (1)

Application Number Title Priority Date Filing Date
CN202110399487.5A Pending CN113064846A (zh) 2021-04-14 2021-04-14 基于Rsockets协议的零拷贝数据传输方法

Country Status (1)

Country Link
CN (1) CN113064846A (zh)

Cited By (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN114201317A (zh) * 2021-12-16 2022-03-18 北京有竹居网络技术有限公司 数据传输方法、装置、存储介质及电子设备
CN114328317A (zh) * 2021-11-30 2022-04-12 苏州浪潮智能科技有限公司 一种提升存储系统通信性能的方法、装置及介质
CN115866010A (zh) * 2023-02-22 2023-03-28 江苏为是科技有限公司 一种rdma连接建立方法及装置
CN117032874A (zh) * 2023-10-08 2023-11-10 统信软件技术有限公司 一种远程控制方法、装置、计算设备及存储介质
CN117591462A (zh) * 2024-01-19 2024-02-23 成都大征创智科技有限公司 一种数字化处理机中基于pcie协议的外设连接方法

Citations (7)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US20080013448A1 (en) * 2006-07-11 2008-01-17 Sony Computer Entertainment Inc. Network Processor System and Network Protocol Processing Method
US20110270943A1 (en) * 2010-04-30 2011-11-03 International Business Machines Corporation Zero copy data transmission in a software based rdma network stack
CN105978985A (zh) * 2016-06-07 2016-09-28 华中科技大学 一种用户态RPC over RDMA的内存管理方法
US20170012844A1 (en) * 2015-07-07 2017-01-12 International Business Machines Corporation Managing network sockets
CN107480080A (zh) * 2017-07-03 2017-12-15 香港红鸟科技股份有限公司 一种基于rdma的零拷贝数据流
CN108600053A (zh) * 2018-05-10 2018-09-28 南京邮电大学 一种基于零拷贝技术的无线网络数据包捕获方法
CN109491809A (zh) * 2018-11-12 2019-03-19 西安微电子技术研究所 一种降低高速总线延迟的通信方法

Patent Citations (7)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US20080013448A1 (en) * 2006-07-11 2008-01-17 Sony Computer Entertainment Inc. Network Processor System and Network Protocol Processing Method
US20110270943A1 (en) * 2010-04-30 2011-11-03 International Business Machines Corporation Zero copy data transmission in a software based rdma network stack
US20170012844A1 (en) * 2015-07-07 2017-01-12 International Business Machines Corporation Managing network sockets
CN105978985A (zh) * 2016-06-07 2016-09-28 华中科技大学 一种用户态RPC over RDMA的内存管理方法
CN107480080A (zh) * 2017-07-03 2017-12-15 香港红鸟科技股份有限公司 一种基于rdma的零拷贝数据流
CN108600053A (zh) * 2018-05-10 2018-09-28 南京邮电大学 一种基于零拷贝技术的无线网络数据包捕获方法
CN109491809A (zh) * 2018-11-12 2019-03-19 西安微电子技术研究所 一种降低高速总线延迟的通信方法

Non-Patent Citations (3)

* Cited by examiner, † Cited by third party
Title
余胜生等: "基于RDMA协议的零拷贝技术研究", 《计算机工程与应用》 *
李胜利等: "基于实时微内核的零拷贝通信协议", 《华中科技大学学报(自然科学版)》 *
王小峰等: "一种TCP/IP卸载的数据零拷贝传输方法", 《计算机工程与科学》 *

Cited By (8)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN114328317A (zh) * 2021-11-30 2022-04-12 苏州浪潮智能科技有限公司 一种提升存储系统通信性能的方法、装置及介质
CN114328317B (zh) * 2021-11-30 2023-07-14 苏州浪潮智能科技有限公司 一种提升存储系统通信性能的方法、装置及介质
CN114201317A (zh) * 2021-12-16 2022-03-18 北京有竹居网络技术有限公司 数据传输方法、装置、存储介质及电子设备
CN114201317B (zh) * 2021-12-16 2024-02-02 北京有竹居网络技术有限公司 数据传输方法、装置、存储介质及电子设备
CN115866010A (zh) * 2023-02-22 2023-03-28 江苏为是科技有限公司 一种rdma连接建立方法及装置
CN117032874A (zh) * 2023-10-08 2023-11-10 统信软件技术有限公司 一种远程控制方法、装置、计算设备及存储介质
CN117032874B (zh) * 2023-10-08 2024-02-23 统信软件技术有限公司 一种远程控制方法、装置、计算设备及存储介质
CN117591462A (zh) * 2024-01-19 2024-02-23 成都大征创智科技有限公司 一种数字化处理机中基于pcie协议的外设连接方法

Similar Documents

Publication Publication Date Title
CN113064846A (zh) 基于Rsockets协议的零拷贝数据传输方法
Cheriton et al. The distributed V kernel and its performance for diskless workstations
EP0889623B1 (en) System and method for efficient remote disk I/O
EP1884085B1 (en) Packet validation in a virtual network interface architecture
US6775700B2 (en) System and method for common information model object manager proxy interface and management
CA2509404C (en) Using direct memory access for performing database operations between two or more machines
US8713180B2 (en) Zero-copy network and file offload for web and application servers
Dubnicki et al. Design and implementation of virtual memory-mapped communication on myrinet
US5768618A (en) Method for performing sequence of actions in device connected to computer in response to specified values being written into snooped sub portions of address space
US20090086732A1 (en) Obtaining a destination address so that a network interface device can write network data without headers directly into host memory
CN111431757B (zh) 虚拟网络的流量采集方法及装置
CN111966446B (zh) 一种容器环境下rdma虚拟化方法
US7171464B1 (en) Method of tracing data traffic on a network
Buonadonna et al. Queue pair IP: a hybrid architecture for system area networks
CN101150487A (zh) 一种零拷贝网络报文发送方法
US9015333B2 (en) Apparatus and methods for handling network file operations over a fibre channel network
CN109564502B (zh) 应用于存储设备中的访问请求的处理方法和装置
CN114640716A (zh) 一种基于快速网络路径的云网络缓存加速系统和方法
CN100486248C (zh) 一种实时环境下的零拷贝通信方法
CN113076281B (zh) 一种Ceph内核客户端进行通信的方法、系统、设备及介质
Mansley Engineering a user-level TCP for the CLAN network
US7827194B2 (en) Access to shared disk device on storage area network
CN113326151A (zh) 进程间通信方法、装置、设备、系统及存储介质
CN107615259A (zh) 一种数据处理方法及系统
US20050141434A1 (en) Method, system, and program for managing buffers

Legal Events

Date Code Title Description
PB01 Publication
PB01 Publication
SE01 Entry into force of request for substantive examination
SE01 Entry into force of request for substantive examination
AD01 Patent right deemed abandoned
AD01 Patent right deemed abandoned

Effective date of abandoning: 20221115