如何处理路基翻浆?:linux 内核开发(零拷贝)
来源:百度文库 编辑:偶看新闻 时间:2024/05/04 04:59:20
linux 内核开发(零拷贝)
我正在写一个linux网卡零拷贝的驱动,是在intel e1000驱动基础之上改动。
查了查资料已经搞清楚DMA是如何运作,而且也知道如何使DMA将数据直接写入自己申请的内存空间。已经有了一个大致的解决方案,但有以下下几个细节搞不定,请同学们帮帮。
我先说下我的思路:
首先从用户太说起,数据包从经数据线至网卡驱动至协议栈最后至用户太要经过至少两次拷贝才能完成,期间cpu参与过多,造成cpu负担过重,效率低下。
从e1000的驱动看到:pci_map_single()这个函数完成了将内核内存映射到DMA设备的过程。我所做的就是将pci_mag_single()映射的内存替换成我申请的内存。这样DMA设备就把数据直接写到指定的内存了,用户台进程读这块内存就OK了。其中没有cpu的参与。
如何替换呢?写过内核的同学们都知道skb buffer这个东西。当网卡驱动被初始化的时候,会netdev_alloc_skb这个系统函数,预先申请一堆的skb buffer。
从源码中看出,申请过程分两个过程,首先申请一个skb buffer结构。skb buffer中有一个指针类型的成员变量data,此时的data是没有指向任何有效数据块的。然后在用kmalloc()申请一块内存,赋给skb->data。网卡驱动就是用pci_map_single()将skb->data映射入DMA设备。然后DMA设备会将收到的数据直接写入skb->data指向的内存区。
所以我们只需增加一个内存分配模块,替换网卡驱动skb buffer的分配函数即可。那是DMA设备会自动的将收到的数据写入我们指定的内存中。
以上是我的思路。不对的地方请指正。
下面是我的问题。
DMA将数据写入我们分配的内存后,就需要通知用户态的进程来读取了。问题如下:
1.用户态如何读取这部分内存。
我查了查资料,有两种方式可以完成。a.使用proc的方式。b.使用ioctrl的方式。由于数据量过大,我希望采用proc的方式。但是对于proc的方式我很不理解。从资料中看到的是在驱动初始化时使用create_proc_entry这个函数,在/proc/目录下建立一个虚拟文件。用户态进程读这个虚拟文件就行了。
struct proc_dir_entry *create_proc_entry(constchar*name, mode_t mode,struct proc_dir_entry *parent)
这个函数会在/proc目录下建立一个文件,OK,没有问题。然后呢,用户态的程序去读该文件,读什么呢,文件建立后里面并没有写入任何有用的东西。我就猜也许是要我自己把我申请的物理内存首地址以及内存大小写入到这个文件中吧。用户态读取文件中的物理地址,使用mmap将物理内存地址映射入自己的进程空间。
这个想发不知对不对。如果不对,请同学给我指明一个思路,谢谢。
2.将内核空间成功映射入用户态进程空间后,网卡驱动如何同用户态的进程同步。
我是这样实现的,我在内核申请了块内存,作为队列。接收过来的数据会被放入队列中。驱动和用户态进程肯定要竞争这个队列,如何同步呢。
3.内核中的内存形式。
用户态进程都有自己的虚拟空间,用户态进程是否有类似的概念呢。还是说内核空间就是被所有内核模块,内核进程所共享的。我看得书中并没有类似概念的说明,请同学们给我扫扫盲。
4.一台机器上会有多块型号相同的网卡,那么这些网卡会使用同样的驱动。
比如有a,b,c三块网卡,型号相同。
a网卡首先被激活,申请一块内存。然后b,c网卡也被激活。a网卡申请的内存会被b.c网卡使用吗。
同学们一起交流,共同提高。
谢谢。
C'est la vie golliwog 查看公开信息 查找 golliwog 发表的更多帖子 查看 golliwog 发表的精华贴 yyyyy
中级会员
#2 2010-10-27, 13:35
我来谈谈我的看法
1. 最好是用/dev/下面的设备文件,而不是proc文件。如果需要在内核与用户态之间共享内存,的确需要用mmap来做,这样不需要进行内存拷贝
2. 在驱动中使用阻塞读取或者实现poll调用
3. 不是很了解,楼下继续
4. 最好是每一块网卡都是使用之间独立的内存空间,可以根据次设备号来区分不同的物理设备 yyyyy 查看公开信息 查找 yyyyy 发表的更多帖子 查看 yyyyy 发表的精华贴 golliwog
中级会员
#3 2010-10-27, 14:49
我在csdn开了个关于0拷贝的话题
有些人的回复给了不错的建议。
等我的问题解决了,就把这个帖子的内容整理一下,给各位参考。 golliwog 查看公开信息 查找 golliwog 发表的更多帖子 查看 golliwog 发表的精华贴 golliwog
中级会员
#4 2010-11-27, 12:50
o(∩_∩)o 哈哈,搞定。。
目前正在做测试。。等测试结果出来后,我把这部分的心得分享一下。
内核的内存结构可真复杂啊。这块费了我好多功夫。
我正在写一个linux网卡零拷贝的驱动,是在intel e1000驱动基础之上改动。
查了查资料已经搞清楚DMA是如何运作,而且也知道如何使DMA将数据直接写入自己申请的内存空间。已经有了一个大致的解决方案,但有以下下几个细节搞不定,请同学们帮帮。
我先说下我的思路:
首先从用户太说起,数据包从经数据线至网卡驱动至协议栈最后至用户太要经过至少两次拷贝才能完成,期间cpu参与过多,造成cpu负担过重,效率低下。
从e1000的驱动看到:pci_map_single()这个函数完成了将内核内存映射到DMA设备的过程。我所做的就是将pci_mag_single()映射的内存替换成我申请的内存。这样DMA设备就把数据直接写到指定的内存了,用户台进程读这块内存就OK了。其中没有cpu的参与。
如何替换呢?写过内核的同学们都知道skb buffer这个东西。当网卡驱动被初始化的时候,会netdev_alloc_skb这个系统函数,预先申请一堆的skb buffer。
从源码中看出,申请过程分两个过程,首先申请一个skb buffer结构。skb buffer中有一个指针类型的成员变量data,此时的data是没有指向任何有效数据块的。然后在用kmalloc()申请一块内存,赋给skb->data。网卡驱动就是用pci_map_single()将skb->data映射入DMA设备。然后DMA设备会将收到的数据直接写入skb->data指向的内存区。
所以我们只需增加一个内存分配模块,替换网卡驱动skb buffer的分配函数即可。那是DMA设备会自动的将收到的数据写入我们指定的内存中。
以上是我的思路。不对的地方请指正。
下面是我的问题。
DMA将数据写入我们分配的内存后,就需要通知用户态的进程来读取了。问题如下:
1.用户态如何读取这部分内存。
我查了查资料,有两种方式可以完成。a.使用proc的方式。b.使用ioctrl的方式。由于数据量过大,我希望采用proc的方式。但是对于proc的方式我很不理解。从资料中看到的是在驱动初始化时使用create_proc_entry这个函数,在/proc/目录下建立一个虚拟文件。用户态进程读这个虚拟文件就行了。
struct proc_dir_entry *create_proc_entry(constchar*name, mode_t mode,struct proc_dir_entry *parent)
这个函数会在/proc目录下建立一个文件,OK,没有问题。然后呢,用户态的程序去读该文件,读什么呢,文件建立后里面并没有写入任何有用的东西。我就猜也许是要我自己把我申请的物理内存首地址以及内存大小写入到这个文件中吧。用户态读取文件中的物理地址,使用mmap将物理内存地址映射入自己的进程空间。
这个想发不知对不对。如果不对,请同学给我指明一个思路,谢谢。
2.将内核空间成功映射入用户态进程空间后,网卡驱动如何同用户态的进程同步。
我是这样实现的,我在内核申请了块内存,作为队列。接收过来的数据会被放入队列中。驱动和用户态进程肯定要竞争这个队列,如何同步呢。
3.内核中的内存形式。
用户态进程都有自己的虚拟空间,用户态进程是否有类似的概念呢。还是说内核空间就是被所有内核模块,内核进程所共享的。我看得书中并没有类似概念的说明,请同学们给我扫扫盲。
4.一台机器上会有多块型号相同的网卡,那么这些网卡会使用同样的驱动。
比如有a,b,c三块网卡,型号相同。
a网卡首先被激活,申请一块内存。然后b,c网卡也被激活。a网卡申请的内存会被b.c网卡使用吗。
同学们一起交流,共同提高。
谢谢。
C'est la vie golliwog 查看公开信息 查找 golliwog 发表的更多帖子 查看 golliwog 发表的精华贴 yyyyy
中级会员
#2 2010-10-27, 13:35
我来谈谈我的看法
1. 最好是用/dev/下面的设备文件,而不是proc文件。如果需要在内核与用户态之间共享内存,的确需要用mmap来做,这样不需要进行内存拷贝
2. 在驱动中使用阻塞读取或者实现poll调用
3. 不是很了解,楼下继续
4. 最好是每一块网卡都是使用之间独立的内存空间,可以根据次设备号来区分不同的物理设备 yyyyy 查看公开信息 查找 yyyyy 发表的更多帖子 查看 yyyyy 发表的精华贴 golliwog
中级会员
#3 2010-10-27, 14:49
我在csdn开了个关于0拷贝的话题
有些人的回复给了不错的建议。
等我的问题解决了,就把这个帖子的内容整理一下,给各位参考。 golliwog 查看公开信息 查找 golliwog 发表的更多帖子 查看 golliwog 发表的精华贴 golliwog
中级会员
#4 2010-11-27, 12:50
o(∩_∩)o 哈哈,搞定。。
目前正在做测试。。等测试结果出来后,我把这部分的心得分享一下。
内核的内存结构可真复杂啊。这块费了我好多功夫。
嵌入式Linux开发一定要了解内核吗?
LINUX内核UML图
怎样更新linux内核
linux 内核 最新版
怎样修改linux内核?
关于linux内核
linux内核编译
Linux内核完全注释中CMOS_READ(addr)函数
下面( )是Linux内核稳定的版本
如何升级linux的内核?
linux最新内核版本是多少?
linux最新内核版本是多少?
linux内核代码的问题~
linux内核代码的问题~
linux内核代码的问题~
linux内核指的是什么?
怎么样看linux内核文件?
怎样升级linux的内核?
请问linux的内核如何编辑哪?
linux的版本debian的内核
求助,升级内核后进不了linux了
哪里有redhat linux最新内核下载???
linux的内核升级的问题
谁告诉我内核linux有什么不一样?