高性能网络I/O框架-netmap源码分析(6) http://blog.chinaunix.net/uid-23629988-id-3803045.html
2015-10-04 14:10
1241 查看
高性能网络I/O框架-netmap源码分析(6) 2013-07-14
22:43:01
分类: LINUX
博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
微博:weibo.com/glinuxer
QQ技术群:4367710
因为最近比较忙,很久没有更新博客了,但是netmap源码分析还没有写完,今天继续分析。这里就显示出了写博客的好处。如果不是写博客,可能自己私下看代码,看了一半,就半途而废了。而写了博客,每次打开自己的主页,看到还未完成的系列,就会坚持把这件事情做完。
唠了一点闲话,也是鼓励大家多写文章,给ChinaUnix贡献一些文字吧。
上次已经把netmap_ioctl分析完了,根据netmap的示例,下面该分析netmap的mmap的实现了。
netmap_fops定义了netmap设备支持的操作
OK,现在我们找到了mmap的入口,linuxnetmapmmap。
在此例中,使用ioctl,得到req.nroffset是ix0网卡的netmap结构的偏移——准确的说是netmap管理网卡结构内存池的偏移。mmap后,mem是netmap内存的映射,而网卡结构内存是内存中的第一项,那么mem同样可以视为netmap管理网卡结构的内存池的起始地址。因此,利用前面的req.nroffset,就得到了ix0的netmap结构,即struct
netmap_if。
(netmap源码分析,未完待续。。。)
22:43:01
分类: LINUX
高性能网络I/O框架-netmap源码分析(6)
作者:gfree.wind@gmail.com博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
微博:weibo.com/glinuxer
QQ技术群:4367710
因为最近比较忙,很久没有更新博客了,但是netmap源码分析还没有写完,今天继续分析。这里就显示出了写博客的好处。如果不是写博客,可能自己私下看代码,看了一半,就半途而废了。而写了博客,每次打开自己的主页,看到还未完成的系列,就会坚持把这件事情做完。
唠了一点闲话,也是鼓励大家多写文章,给ChinaUnix贡献一些文字吧。
上次已经把netmap_ioctl分析完了,根据netmap的示例,下面该分析netmap的mmap的实现了。
定位netmap的mmap
前文提到过netmap会创建一个设备static struct miscdevice netmap_cdevsw = { /* same name as FreeBSD */ MISC_DYNAMIC_MINOR, "netmap", &netmap_fops, };
netmap_fops定义了netmap设备支持的操作
static struct file_operations netmap_fops = { .mmap = linux_netmap_mmap, LIN_IOCTL_NAME = linux_netmap_ioctl, .poll = linux_netmap_poll, .release = netmap_release, };
OK,现在我们找到了mmap的入口,linuxnetmapmmap。
linux_netmap_mmap分析
现在直接进入linux_netmap_mmap的代码static int linux_netmap_mmap(struct file *f, struct vm_area_struct *vma) { int lut_skip, i, j; int user_skip = 0; struct lut_entry *l_entry; const struct netmap_obj_pool *p[] = { nm_mem->nm_if_pool, nm_mem->nm_ring_pool, nm_mem->nm_buf_pool }; /* * vma->vm_start: start of mapping user address space * vma->vm_end: end of the mapping user address space */ /* 这里又是一个编程技巧,使用(void)f既不会产生任何真正的代码,又可以消除变量f没有使用的warning。 为什么f不使用,还会出现在参数列表中呢?没办法啊,只是Linux框架决定的。linux_netmap_mmap只是一个注册回调,自然要遵从linux的框架了。 */ (void)f; /* UNUSED */ // XXX security checks for (i = 0; i < 3; i++) { /* loop through obj_pools */ /* * In each pool memory is allocated in clusters * of size _clustsize , each containing clustentries * entries. For each object k we already store the * vtophys malling in lut[k] so we use that, scanning * the lut[] array in steps of clustentries, * and we map each cluster (not individual pages, * it would be overkill). */ /* 上面的注释说的很明白。 每个pool里的object都是由_clustsize组成的,每一个都包含clustertries个基础内存块。 一个pool公有_numclusters个基础内存块。 所以,在进行内存映射的时候,user_skip表示已经映射的内存大小,vma->start+user_skip也就是当前未映射内存的起始地址,lut_skip表示当前待映射的物理内存池的块索引 */ for (lut_skip = 0, j = 0; j < p[i]->_numclusters; j++) { l_entry = &p[i]->lut[lut_skip]; if (remap_pfn_range(vma, vma->vm_start + user_skip, l_entry->paddr >> PAGE_SHIFT, p[i]->_clustsize, vma->vm_page_prot)) return -EAGAIN; // XXX check return value lut_skip += p[i]->clustentries; user_skip += p[i]->_clustsize; } } /* 循环执行完毕后,netmap在内核中的3个对象池已经完全映射到用户空间 真正执行映射的函数是remap_pfn_range,这是内核函数,用于将内核空间映射到用户空间 这个函数超出了本文的主题范围了,我们只需要知道它是做什么的就行了。 */ return 0; }
用户态得到对应网卡的netmap结构
在将netmap内核态的内存映射到用户空间以后,netmap的示例通过offset来得到对应网卡的netmap结构。fd = open("/dev/netmap", 0); strcpy(req.nr_name, "ix0"); // register the interface ioctl(fd, NIOCREG, &req); // offset of the structure mem = mmap(NULL, req.nr_memsize, PROT_READ|PROT_WRITE, 0, fd, 0); nifp = NETMAP_IF(mem, req.nr_offset);
在此例中,使用ioctl,得到req.nroffset是ix0网卡的netmap结构的偏移——准确的说是netmap管理网卡结构内存池的偏移。mmap后,mem是netmap内存的映射,而网卡结构内存是内存中的第一项,那么mem同样可以视为netmap管理网卡结构的内存池的起始地址。因此,利用前面的req.nroffset,就得到了ix0的netmap结构,即struct
netmap_if。
走读netmap的示例中工作代码
按照netmap示例,马上就要进入netmap真正工作的代码了。for (;;) { struct pollfd x[1]; /* 根据netmap的代码,NETMAP_RXRING的定义如下 #define NETMAP_RXRING(nifp, index) \ ((struct netmap_ring *)((char *)(nifp) + \ (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] ) ) 得到该网卡的接收ring buffer。 吐个槽,为什么英文接收Receive要缩写为RX呢。。。我在别的地方也见过。 */ struct netmap_ring *ring = NETMAP_RX_RING(nifp, 0); x[0].fd = fd; x[0].events = POLLIN; /* 超时1秒等接收事件发生 */ poll(x, 1, 1000); /* 收到ring->avail个包 */ for ( ; ring->avail > 0 ; ring->avail--) { /* 得到当前包索引 */ i = ring->cur; /* 得到对应的数据包 */ buf = NETMAP_BUF(ring, i); /* 用户态处理该数据包 */ use_data(buf, ring->slot[i].len); /* 移到下一个待处理数据包 */ ring->cur = NETMAP_NEXT(ring, i); } }
(netmap源码分析,未完待续。。。)
相关文章推荐
- 高性能网络I/O框架-netmap源码分析(5) http://blog.chinaunix.net/uid-23629988-id-3693204.html
- 高性能网络I/O框架-netmap源码分析(4) http://blog.chinaunix.net/uid-23629988-id-3642305.html
- 高性能网络I/O框架-netmap源码分析(3) http://blog.chinaunix.net/uid-23629988-id-3614187.html
- 高性能网络I/O框架-netmap源码分析(2) http://blog.chinaunix.net/uid-23629988-id-3608622.html
- 高性能网络I/O框架-netmap源码分析(1) http://blog.chinaunix.net/uid-23629988-id-3594118.html
- ios如何进行网络的推送
- epoll是如何监控多个描述符及如何获得通知(1) http://blog.chinaunix.net/uid-23629988-id-3569332.html
- epoll是如何监控多个描述符及如何获得通知(2) http://blog.chinaunix.net/uid-23629988-id-3575499.html?/gov-17311/
- 《TCP/IP详解 卷一:协议》读书笔记--RARP:逆地址解析协议
- 网络与并发
- RPC协议、http协议、tcp/ip协议、udp协议、socket协议以及soap协议都有什么相同点和不同点
- 《社交网络》里的评分公式——ELO排名系统
- HTTP协议详解----HTTP消息
- 网络基础知识系列:阐述VLAN和Trunk
- iOS讲解迷惑深入浅出之开启子线程请求网络
- 不容忽视的网络安全
- TCP协议
- android Jsoup获取网站内容(实例为新闻标题获取),android网络必学
- HTTP 知识点
- 网络编程第三方 时间选择器