Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51398
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 147
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-03 11:00
个人简介

navigation、linux、内核、网络技术、网卡驱动、qt、android、ios、irrlicht、ogre

文章分类

全部博文(11)

文章存档

2016年(1)

2013年(10)

我的朋友

分类: LINUX

2013-04-15 20:26:23

      关注过零拷贝网卡抓包的朋友都知道,零拷贝里面很重要的一点就是,用户程序直接可以取得来自内核的包,这样就去掉了层层拷贝,同时也不占用服务器的cpu。这里大致的说一下我这边对这个的理解,
结合我现在能运行的程序对其进行一个简单的描述。
     1、首先我们需要在dev下面建立一个虚拟设备,名字叫做zcmem,这里有两个方法可以建立,第一个方法是直接mknod指令创建设备,第二种是使用 misc_register函数创建设备。此次我是使用第二种方法建立的设备。
          这个虚拟设备就变成了用户程序和内核之间的连接纽带。内核会往这个地方写数据,用户程序从这里取数据。
     2、在内核层次我们会定义一个全局的struct file_operation, 大致会定义出来一下这些成员函数。然后将这个全局变量赋值给第一步中的 struct miscdev的fops成员。
          .open = zc_open,           //当用户程序执行open("/dev/zcmem", O_RDWR) 的时候会调用此函数,同时还会生成一个struct file指针, 我们可以再这里给file的private_data赋值。然后在下面所示函数中将对应的结构取出来
           .release = zc_release,      //释放函数
           .unlocked_ioctl = zc_unlocked_ioctl,   //处理用户程序中的ioctl指令
           .mmap    = zc_mmap,      //在这个里面做映射,将内核中申请的内存映射到用户空间
     3、用户进程打开fd =open("/dev/zcmem", O_RDWR),利用ioctl发送控制信息
     4、利用dev_get_by_name将真正的网卡设备取出来和你建立的虚拟设备绑定在一起,其实也就是为之后的remap_pfn_range映射做准备,并且在内核空间中申请内存。
     5、用户程序里面使用mmap映射mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 注意,这里的fd是步骤3中打开fd。
         注:这里会做一下操作:1)在进程的虚拟空间查找一块vma  2)
对vma进行映射  3)调用驱动程序中的mmap函数,就是上面的zc_mmap。4)将vma插入到vma链表中
     6、驱动程序调用zc_mmap函数,注意此函数的第二个参数就是5中生成的vma结构体指针struct vm_area_struct,此结构包括了映射范围。内核空间使用remap_pfn_range将在内核申请的空间映射到此结构对应的范围即可.
     经过以上几步,内核就将数据写到用户程序可以直接取得地方了。
     
    
 
阅读(1512) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~