专利名称:一种零拷贝接收报文的方法和系统的制作方法
技术领域:
本发明涉及高速网络收包领域,尤其涉及一种零拷贝接收报文的方法和系统。
背景技术:
在Linux操作系统中,用户态程序捕获网卡接收到的数据包一般是通过套接字相关的系统调用网卡通过DMA (Direct Memory Access,直接内存存取)机制将网络数据包接收到内核空间,进程通过读套接字将数据从内核空间复制到用户空间。在这种模式下,用户进程接收数据需要一次从内核到用户空间的数据复制。在高速网络中,大量的数据拷贝极大的消耗了 CPU资源,系统调用会引起操作系统上下文切换,降低了系统性能。为了解决这个问题,目前存在一种零拷贝技术,该零拷贝的思想是数据包在从网卡到达用户空间的过程中,通过硬件DMA技术和操作系统MMAP (Memory Map)技术,将报文直接送到用户空间,实现CPU的零参与,彻底消除CPU在这方面的损耗。上述零拷贝技术需要修改网卡驱动,当网卡驱动升级时,还需要做相应的修改。具体地,现在的零拷贝普遍采用的做法,如图1所示,包括先在内核中分配一片固定的空间,将这块空间分成多个固定长度的数据块,组成一个队列;然后修改网卡驱动程序,更改为接收缓冲区分配内存的函数,所有内存都从上述队列中分配;调用MMAP系统调用将上述队列映射到用户空间;网卡驱动收到数据后,给数据块设置标记,表示数据接收完成;用户空间根据标记,直接读取数据。然而,上述零拷贝技术存在以下缺陷上述的零拷贝技术可以应用于IDSantrusion Detection System,入侵检测系统)等监听性质的应用中。因为IDS只需要简单的将报文送到IDS检测引擎,不需要经过其他模块。但是在UTM(Unified Threat Management,企业上网安全隐患)中,由于数据在送到运行于用户空间的IPSantrusion Protection System,互联网协议群)等引擎时,要经过TCP/IP协议栈,在协议栈里完成IP碎片重组等操作,导致报文长度、位置发生变化,不再处于上述的队列中,从用户空间就无法读取这段数据。且上述的固定空间由于大小受限制,在网络突发高峰的时候,会产生缓冲区不足导致丢包的情况。
发明内容
本发明提供一种零拷贝接收报文的方法和系统,用以解决现有技术中采用的零拷贝技术不能读取缓冲区中变化的数据,以及在网络高峰期时由于缓冲区不足导致丢包等问题。为了解决上述技术问题,本发明采用的技术方案如下一方面,本发明提供一种零拷贝接收报文的方法,包括用户态进程打开预先创建的虚拟字符设备,调用所述虚拟字符设备提供的mmap 方法;内核态进程在所述mmap方法被调用时,将所有内核低端空间映射到用户空间,并为所述内核低端空间的结构Vm_area_StruCt设置nopage方法;
内核态进程在网卡设备接收到数据包时,基于所述数据包在所述内核低端空间中的地址,得到数据包存储偏移地址后传递给用户态进程;用户态进程根据所述偏移地址计算得到待访问的虚拟地址,并在访问所述虚拟地址时,触发CPU缺页异常,使得操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项;用户态进程基于所述页目录和页表项,读取存储在所述内核低端空间内的所述数据包。进一步地,本发明所述方法中,所述用户态进程根据所述偏移地址计算得到待访问的虚拟地址的方式包括所述用户态进程将所述数据包的存储偏移地址加上映射的用户空间地址,得到读取所述数据包所需访问的虚拟地址。进一步地,本发明所述方法中,所述操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项,具体包括操作系统将要访问的所述虚拟地址减去所述用户空间的起始虚拟地址,得到一个偏移地址,并根据该偏移地址得到要访问的物理地址;操作系统将所述物理地址右移PAGE_SHIFT位转换成页帧号,再调用pfn_t0_page 函数返回page结构指针;操作系统取得所述page结构指针后,为所述物理地址设置页目录和页表项。进一步地,本发明所述方法中,所述操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项前,还包括所述操作系统调用缺页异常处理函数检测所述虚拟地址所在用户空间的合法性, 当所述用户空间合法时,调用所述nopage方法。进一步地,本发明所述方法中,所述网卡设备接收到所述数据包时,具体包括所述网卡驱动调用系统函数all0C_Skb()为网卡分配缓存,并利用所述系统函数 alloc_skb ()调用内存分配函数kmallocO分配内存块;所述网卡驱动通过直接内存存取方式将所述数据包存到所述缓存中。其中,所述网卡驱动将所述数据包存到所述缓存后还包括操作系统的TCP/IP协议栈对所述数据包进行处理。另一方面,本发明还提供一种零拷贝接收报文的系统,包括初始化模块,用于打开预先创建的虚拟字符设备,调用所述虚拟字符设备提供的 mmap方法;映射模块,用于在所述mmap方法被调用时,将所有内核低端空间映射到用户空间,并为所述内核低端空间的结构Vm_area_StruCt设置nopage方法;地址计算模块,用于在网卡设备接收到数据包时,基于所述数据包在所述内核低端空间中的地址,得到数据包存储偏移地址后传递给地址访问模块;地址访问模块,用于根据所述偏移地址计算得到待访问的虚拟地址,并在访问所述虚拟地址时,触发CPU缺页异常;Page获取模块,用于在所述地址访问模块触发CPU缺页异常时,调用所述nopage 方法得到要访问的物理地址对应的页目录和页表项;
报文读取模块,用于基于所述物理地址对应的页目录和页表项,读取存储在所述内核低端空间内的所述数据包。进一步地,本发明所述系统中,所述I^age获取模块具体包括物理地址计算子模块,用于将要访问的所述虚拟地址减去所述用户空间的起始虚拟地址,得到一个偏移地址,并根据该偏移地址计算要访问的物理地址;Page指针获取子模块,用于将所述物理地址右移PAGE_SHIFT位转换成页帧号,再调用pfn_to_page函数返回page结构指针;Page项设置子模块,用于在所述I^ge指针获取模块取得所述page结构指针后,为所述物理地址设置页目录和页表项。进一步地,本发明所述系统中,所述地址计算模块具体用于,将所述数据包的存储偏移地址加上映射的用户空间地址,得到读取所述数据包所需访问的虚拟地址。进一步地,本发明所述系统中,所述网卡设备具体包括数据包接收模块,用于接收到所述数据包时,调用系统函数allOC_SlA0为网卡分配缓存,并利用所述系统函数allOC_SlA0调用内存分配函数kmallocO分配内存块;数据包存储模块,用于通过直接内存存取方式将所述数据包存到所述缓存中。与现有技术相比,本发明有益效果如下首先,本发明克服了为网卡分配固定缓存区存在的缓冲区不足的问题,提高了系统在高峰时的处理能力。其次,本发明解决了常规零拷贝过程中报文不能被任意修改或移动的问题。第三,本发明不需要修改现有的网卡驱动,改造成本为零。
图1为现有技术中零拷贝技术的实现示意图;图2为本发明提供的一种零拷贝接收报文的方法流程图;图3为本发明实施例中所述零拷贝接收报文的方法示意图;图4为本发明提供的一种零拷贝接收报文的系统结构框图。
具体实施例方式下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。为了解决现有技术中采用的零拷贝技术不能读取缓冲区中变化的数据,以及在网络高峰期时由于缓冲区不足导致丢包等问题,本发明提供一种零拷贝接收报文的方法和系统。如图2所示,本发明提供的零拷贝接收报文的方法,包括步骤S201、用户态进程打开预先创建的虚拟字符设备,调用所述虚拟字符设备提供的mmap方法;内核态进程在所述mmap方法被调用时,将所有内核低端空间映射到用户空间,并为所述内核低端空间的结构Vm_area_StruCt设置nopage方法;
6
步骤S202、内核态进程在网卡设备接收到数据包时,基于所述数据包在所述内核低端空间中的地址,得到数据包存储偏移地址后传递给用户态进程;步骤S203、用户态进程根据所述偏移地址计算得到待访问的虚拟地址,并在访问所述虚拟地址时,触发CPU缺页异常,使得操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项;具体地,该步骤中,用户态进程根据所述偏移地址计算得到待访问的虚拟地址的方式包括用户态进程将所述数据包的存储偏移地址加上映射的用户空间地址,得到读取所述数据包所需访问的虚拟地址。具体地,该步骤中,操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项,包括(1)操作系统将要访问的所述虚拟地址减去所述用户空间的起始虚拟地址,得到一个偏移地址,并根据该偏移地址得到要访问的物理地址;(2)操作系统将所述物理地址右移PAGE_SHIFT位转换成页帧号,再调用pfn_to_ page函数返回page结构指针;(3)操作系统取得所述page结构指针后,为所述物理地址设置页目录和页表项。步骤S204、用户态进程基于所述页目录和页表项,读取存储在所述内核低端空间内的所述数据包。为了更清楚的表述本发明,下面给出本发明的一个较佳实施例,并结合对实施例的描述进一步给出本发明的技术细节。本发明实施例所述的零拷贝接收报文的方法示意图如图3所示,所述零拷贝接收报文方法具体通过如下几个过程实现一,创建虚拟字符设备;内核态进程用regi ster_ChrdeV函数创建一个虚拟的字符设备,并初始化其 file_operations结构,初始化与该虚拟字符设备相关的内存映射(mmap)方法;其中,内存映射方法具体为初始化内存空间控制结构Vm_area_StruCt,设置其 nopage 方法。其中,file_operations结构定义如下static struct file—operations ipq_fops = { open: ipq_open, release: ipq_release, read: ipq_read, write: ipq_write, poll: ipq_poll, unlocked—ioctl: ipq_ioctl, mmap:ipq_mmap,
};S卩,虚拟字符设备可以有以下操作打开、释放、读、写、推、解锁以及mmap内存映射方法。本发明实施例中,创建虚拟字符设备是为了使用虚拟字符设备提供的mmap方法 (即上述结构中的ipq_mma0070),所述mmap方法用于将所有低端内核空间(低端内存)映射到用户空间。在典型的32位Linux系统中,低端内存的物理地址是0 0x30000000,总大小768M字节,远小于用户进程拥有的地址空间3G字节。另外,需要注意的是,本发明实施例所述mmap方法并不立即为用户态进程设置低端内存的内存页目录和页表项,只是简单的为表示该低端内存空间的结构vm_area_ struct (虚拟内存区域)设置nopage方法,页目录和页表项是在过程中发生缺页异常时设置的。 其中,为vm_area_sturct设置nopage方法通过代码实现如下static Struct vm—oprations—struct ipq_nopage_vm_ops = {
.open = ipq_vma_open,
.close = ipq_vma—close,
.nopage = ipq_vma_nopage, /* nopage 方法 */
};S卩,表示vm_area_sturct可以进行打开、关闭以及实现nopage方法。二,用户态进程数据包接收初始化;用户态进程打开创建的虚拟字符设备,获得文件描述符;其中,虚拟字符设备打开方法实现如下:fd = open(" /dev/ipq",0_RDWR);用户态进程调用sysinfo函数获取内核低端内存的大小;用户态进程调用虚拟字符设备提供的mmap内存映射方法;内核态进程在mmap内存映射方法被调用时,将所有的低端内存映射到用户空间, 并为内存空间的控制结构vm_area_StruCt设置nopage方法。其中,mmap内存映射操作的返回值就是映射内存的用户空间地址,用户态程序访问这段用户空间地址实际上就是访问整个内核态的低端内存空间。
三,网卡设备接收数据包;1,网卡驱动调用操作系统的all0C_Skb()函数为网卡分配缓存,所述alloc_ skb ()函数会调用kmallocO函数分配大约I大小的内存块;其中,kmallocO函数的参数是GFP_AT0MIC,所以内存块都是从操作系统的低端内存中分配的,这就是数据包接收程序只映射低端内存,就能够随意访问报文的原因。2,网卡驱动通过DMA方式将数据包存到缓存中,且所述缓存中的数据包可以通过操作系统中的TCP/IP协议栈进行处理。四,用户态进程读取缓存内的数据包;当网卡设备将接收的数据包存到缓存后,内核态进程负责计算数据包存储在内核低端内存的存储偏移地址,并将该偏移地址传送给用户态进程kmem_0ffset = (_u32) skb- > data-PAGE_OFFSET ;用户态进程将所述偏移地址加上映射地址就得到读取相应数据包所需访问的虚 以地址,艮口 char^bp = (unsigned char水)rg. kmem+kmem—offset ;当用户态进程第一次试图访问用户空间的上述虚拟地址时,会触发CPU缺页异常,操作系统的缺页异常处理函数在确认该用户空间合法后,会调用nopage方法,得到该用户空间所在页对应的物理页面,然后为该物理页设置页目录和页表项,用户态进程得到相应的页目录和页表项后,即可读取低端内存内缓存的数据包。其中,调用nopage方法得到该用户空间所在页对应的物理页面,具体为1,将要访问的虚拟地址,减去上述用户空间的起始虚拟地址,得到偏移地址,然后根据该偏移地址计算出要访问的物理地址;通常情况下,这个偏移地址就等于物理地址。2,将物理地址右移PAGE_SHIFT位,转换成页帧号,然后调用pfn_t0_page函数返回page结构指针。3,操作系统取得page结构指针后,为上述物理地址设置页目录和页表项。上述nopage方法通过代码实现如下struct page* ipq_vma_nopage(struct vm—area—struct* vma, unsigned long address, int * type)
{
struct page* pageptr;
unsigned long offset = vma->vm_pgoff PAGE—SHIFT; unsigned long pos = address - vma->vm—start + offset; unsigned long pages = pos PAGE— SHIFT;
pageptr = pfn_to_page(pages);
get_page(pageptr);
return pageptr;
}综上所述,本发明提供的方法,克服了为网卡分配固定缓存区存在的缓冲区不足的问题,提高了系统在高峰时的处理能力;解决了常规零拷贝过程中报文不能被任意修改或移动的问题;并且本发明所述方法不需要修改现有的网卡驱动,改造成本为零。如图4所示,本发明还提供一种零拷贝接收报文的系统,包括初始化模块,用于打开预先创建的虚拟字符设备,调用所述虚拟字符设备提供的 mmap方法;映射模块,用于在所述mmap方法被调用时,将所有内核低端空间映射到用户空间,并为所述内核低端空间的结构Vm_area_StruCt设置nopage方法;地址计算模块,用于在网卡设备接收到数据包时,基于所述数据包在所述内核低端空间中的地址,得到数据包存储偏移地址后传递给地址访问模块;地址访问模块,用于根据所述偏移地址计算得到待访问的虚拟地址,并在访问所述虚拟地址时,触发CPU缺页异常;Page获取模块,用于在所述地址访问模块触发CPU缺页异常时,调用所述nopage 方法得到要访问的物理地址对应的页目录和页表项;报文读取模块,用于基于所述物理地址对应的页目录和页表项,读取存储在所述内核低端空间内的所述数据包。进一步地,上述I^age获取模块,具体包括 物理地址计算子模块,用于将要访问的所述虚拟地址减去所述用户空间的起始虚拟地址,得到一个偏移地址,并根据该偏移地址计算要访问的物理地址;Page指针获取子模块,用于将所述物理地址右移PAGE_SHIFT位转换成页帧号,再调用pfn_to_page函数返回page结构指针;Page项设置子模块,用于在所述I^age指针获取模块取得所述page结构指针后,为所述物理地址设置页目录和页表项。
进一步地,上述地址计算模块,具体用于将所述数据包的存储偏移地址加上映射的用户空间地址,得到读取所述数据包所需访问的虚拟地址。进一步地,本发明所述系统中,所述网卡设备具体包括数据包接收模块,用于接收到所述数据包时,调用系统函数allOC_SlA0为网卡分配缓存,并利用所述系统函数allOC_SlA0调用内存分配函数kmallocO分配内存块;数据包存储模块,用于通过直接内存存取方式将所述数据包存到所述缓存中。综上所述,本发明提供的系统,克服了为网卡分配固定缓存区存在的缓冲区不足的问题,提高了系统在高峰时的处理能力;解决了常规零拷贝过程中报文不能被任意修改或移动的问题;并且本发明所述系统不需要修改现有的网卡驱动,改造成本为零。显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。
权利要求
1.一种零拷贝接收报文的方法,其特征在于,包括用户态进程打开预先创建的虚拟字符设备,调用所述虚拟字符设备提供的mmap方法; 内核态进程在所述mmap方法被调用时,将所有内核低端空间映射到用户空间,并为所述内核低端空间的结构vm_area_StruCt设置nopage方法;内核态进程在网卡设备接收到数据包时,基于所述数据包在所述内核低端空间中的地址,得到数据包存储偏移地址后传递给用户态进程;用户态进程根据所述偏移地址计算得到待访问的虚拟地址,并在访问所述虚拟地址时,触发CPU缺页异常,使得操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项;用户态进程基于所述页目录和页表项,读取存储在所述内核低端空间内的所述数据包。
2.如权利要求1所述的方法,其特征在于,所述用户态进程根据所述偏移地址计算得到待访问的虚拟地址的方式包括所述用户态进程将所述数据包的存储偏移地址加上映射的用户空间地址,得到读取所述数据包所需访问的虚拟地址。
3.如权利要求1所述的方法,其特征在于,所述操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项,具体包括操作系统将要访问的所述虚拟地址减去所述用户空间的起始虚拟地址,得到一个偏移地址,并根据该偏移地址得到要访问的物理地址;操作系统将所述物理地址右移PAGE_SHIFT位转换成页帧号,再调用pfn_t0_page函数返回page结构指针;操作系统取得所述page结构指针后,为所述物理地址设置页目录和页表项。
4.如权利要求3所述的方法,其特征在于,所述操作系统调用所述nopage方法得到要访问的物理地址对应的页目录和页表项前,还包括所述操作系统调用缺页异常处理函数检测所述虚拟地址所在用户空间的合法性,当所述用户空间合法时,调用所述nopage方法。
5.如权利要求1所述的方法,其特征在于,所述网卡设备接收到所述数据包时,具体包括所述网卡驱动调用系统函数allOC_SlA0为网卡分配缓存,并利用所述系统函数 alloc_skb()调用内存分配函数kmal IocO分配内存块;所述网卡驱动通过直接内存存取方式将所述数据包存到所述缓存中。
6.如权利要求5所述的方法,其特征在于,所述网卡驱动将所述数据包存到所述缓存后还包括操作系统的TCP/IP协议栈对所述数据包进行处理。
7.一种零拷贝接收报文的系统,其特征在于,包括初始化模块,用于打开预先创建的虚拟字符设备,调用所述虚拟字符设备提供的mmap 方法;映射模块,用于在所述mmap方法被调用时,将所有内核低端空间映射到用户空间,并为所述内核低端空间的结构Vm_area_StruCt设置nopage方法;地址计算模块,用于在网卡设备接收到数据包时,基于所述数据包在所述内核低端空间中的地址,得到数据包存储偏移地址后传递给地址访问模块;地址访问模块,用于根据所述偏移地址计算得到待访问的虚拟地址,并在访问所述虚拟地址时,触发CPU缺页异常;Page获取模块,用于在所述地址访问模块触发CPU缺页异常时,调用所述nopage方法得到要访问的物理地址对应的页目录和页表项;报文读取模块,用于基于所述物理地址对应的页目录和页表项,读取存储在所述内核低端空间内的所述数据包。
8.如权利要求7所述的系统,其特征在于,所述I^age获取模块具体包括物理地址计算子模块,用于将要访问的所述虚拟地址减去所述用户空间的起始虚拟地址,得到一个偏移地址,并根据该偏移地址计算要访问的物理地址;Page指针获取子模块,用于将所述物理地址右移PAGE_SHIFT位转换成页帧号,再调用 pfn_to_page函数返回page结构指针;I^age项设置子模块,用于在所述Page指针获取模块取得所述page结构指针后,为所述物理地址设置页目录和页表项。
9.如权利要求7所述的系统,其特征在于,所述地址计算模块具体用于,将所述数据包的存储偏移地址加上映射的用户空间地址,得到读取所述数据包所需访问的虚拟地址。
10.如权利要求7所述的系统,其特征在于,所述网卡设备具体包括数据包接收模块,用于接收到所述数据包时,调用系统函数all0C_S!A ()为网卡分配缓存,并利用所述系统函数alloc_SlA0调用内存分配函数kmallocO分配内存块; 数据包存储模块,用于通过直接内存存取方式将所述数据包存到所述缓存中
全文摘要
本发明公开了一种零拷贝接收报文的方法和系统,所述方法包括用户态进程打开预先创建的虚拟字符设备,调用mmap方法;内核态进程在mmap方法被调用时,将所有内核低端空间映射到用户空间,并为其的结构vm_area_struct设置nopage方法;内核态进程在网卡设备接收到数据包时,将数据包在低端内存空间中的偏移地址传递给用户态进程;用户态进程访问计算出的虚拟地址,触发CPU缺页异常,使得操作系统调用nopage方法得到要访问的物理地址对应的页目录和页表项;用户态进程读取存储在所述低端内核地址空间内的所述数据包。本发明解决了已有零拷贝技术缓冲区不足以及零拷贝过程中报文不能被任意修改或移动的问题。
文档编号H04L12/56GK102402487SQ20111036190
公开日2012年4月4日 申请日期2011年11月15日 优先权日2011年11月15日
发明者刘彤 申请人:北京天融信科技有限公司