我正在研究NDIS过滤器驱动程序,它实际上将数据从NET_BUFFER复制到发送路径中的驱动程序分配的缓冲区,并将这些驱动程序分配的缓冲区推送到内部队列。稍后,数据将从队列中的这些驱动程序分配的缓冲区再次复制到IRP缓冲区。我想避免这个数据副本。
在Linux中,我们可以创建一个skbuff的克隆,克隆的skbuff可以排队等待以后使用。 Windows中是否也有类似的选项?如果有办法克隆NET_BUFFER,我们可以简单地避免从NET_BUFFER发生的第一个副本到驱动程序分配的内存缓冲区。
如果存在从NetBufferLists到IRP缓冲区实现零拷贝的方法,那么它真的是一个理想的解决方案。如果有人可以提出更好的解决方案来避免发送路径中的副本,那将会非常有用。
答案 0 :(得分:3)
我不清楚为什么你需要复制NB(NET_BUFFER)。如果您计划将NB排入其他线程进行处理,则可以使用原始NB进行处理 - 无需复制任何内容。
此处您需要复制有效负载的唯一原因是您计划暂停一段时间(例如,超过1000毫秒)。在较高级别,与NB相关联的有效负载属于应用程序。 NDIS允许您对NB进行排队,进行一些处理,删除,修改它等等。但是(取决于套接字选项)应用程序可能会被卡住,直到其缓冲区完成为止。因此,您无法无限期地挂起原始NB或其有效负载 。如果您要做一些需要很长时间的事情,那么您应该分配所需的所有数据结构的深层副本(NBL,NB,MDL和有效负载缓冲区)并将原始文件返回给应用
如果您将数据包有效负载填充到IRP中以便用户模式进程可以考虑有效负载,那么您确实需要1个副本。原因是内核不能信任任何用户模式进程在特定时间预算内做任何事情。想象一下,例如,系统将进入休眠状态。内核适当地暂停所有用户模式进程,然后等待每个设备进入低功耗状态。但是网卡无法进入低功耗状态,因为数据路径不会暂停,因为某些数据包卡在您的过滤器驱动程序中,等待(现已暂停)用户模式进程进行回复。因此,您可以通过网络设备将IO与IO分离到用户模式来保护自己:制作副本。
但是,如果您所做的只是将数据包发送到另一个执行(比如说)加密的内核设备,那么您可以假设加密设备确保合理的时间预算,因此可以安全地给出原始数据包有效负载。