数据包零拷贝

下文是对工作中的零拷贝机制进行主要代码注释描述,以便之后能够快速记忆和理清其工作原理。

1、物理内存的分配,代码与内核一起编译,内核启动执行do_early_param进行分配
__initcall (capmem_init)                                                                      //相当于module_init,内核启动流程do_initcalls()会遍历.initcall*.init段,依次执行各个级别的函数
capmem_init
  create_proc_info_entry("capture_mem",0444,&proc_root,get_info))  //proc显示capmem大小等信息

//__setup宏用来指导建立obs_kernel_param结构,并编译到内核特定段中。在内核启动时,do_early_param将取出__setup_start到__setup_end之间obs_kernel_param结构并执行其中的函数
__setup("capmem=", capmem_setup);//获取grub、bootload等引导程序传给内核的参数,capmem设置待分配物理内存大小
capmem_setup
  capmem = alloc_bootmem_low_pages(capmem_pages<<PAGE_SHIFT);//bootmem分配器分配内存,内存分配的任务,这个时候buddy系统,slab分配器等并没有被初始化好

2、使用内核模块注册proc文件系统,实现对内核缓存初始化、参数配置、对内核资源的控制、缓存映射等功能。
/*
缓存描述符中的映射缓存结构体,mmap将其映射到应用层,应用层有与之对应的相同的结构体
*/
typedef struct  _mapbuffer
{
                        int dwWrite;        // 读地址
           int dwRead;        // 写地址
           int dwPacketSum; //能存放包的总数
           DATAPACKET  pDataPacket[MAX_PACKET_SUM];
}MAPBUFFER;


/*
缓存描述符,描述当前缓存是属于哪个网卡通道、几号内核缓存、缓存的的大小、缓存的过滤参数
读写指针位置、和当前存放的数据帧的个数等信息。描述符以链表形式挂接,链表描述多个内核缓存。
*/
typedef struct  _kbuffer
{
                     MAPBUFFER     *pMapBuffer; //存放映射buffer信息的地址
         int        dwKBNum;//内核缓存的计数值
         int        dwEthNum;//属于哪个网卡的标示符,以数字标示
         char        ethName[20]; //属于哪个网卡的标示符,以字符型数字标示
         FILTER_ARG    filter_arg;//过滤参数
        unsigned char rece_flag; //接收标志
        int        pdwFlowIp1[FLOW_COUNT];//流量的ip地址1
        int        pdwFlowIp2[FLOW_COUNT];//流量的ip地址2
        int            flow_count;//流量的计数值
        int            flow_sum;//流量的种类种数
                                struct  _kbuffer    *next;//下一个通道缓存的地址
}KBUFFER;


mmap 在proc内核的实现
  paddr = virt_to_phys((void*)((unsigned long)( pKB->pMapBuffer)));                            //找到其映射后对应的物理内存
  remap_pfn_range(vma, vma->vm_start, paddr >> PAGE_SHIFT, size, PAGE_SHARED) //将内核空间的物理内存映射到用户空间

3、在网卡驱动中断处理rx将数据抛向协议栈之前,把sk_buf->data(数据帧)写入缓存
轮询缓存描述符链表,判断网卡通道是否与接收数据帧的netdev是否一致,如果相同就写入相对应
的映射缓存区。写入成功便将该skb释放,不再抛给协议栈,节省系统处理数据包的资源,减轻cpu压力


4、应用层的使用
fd=open("/proc/cap", O_RDWR)           //open proc
ioctl(fd, INIT_KB, &kb_io)                     //ioctl设置网卡混杂模式
addr=mmap(0, sizeof(MAPBUFFER), PROT_READ|PROT_WRITE,MAP_SHARED|MAP_LOCKED, fd, iKBStart);  //映射
pKBuffer->pMapBuffer = (MAPBUFFER *)adr;   //映射数据缓存结构化,使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值