零复制udp套接字使用sendfile而不是sendto

时间:2017-04-06 09:24:42

标签: c linux sockets

我在实时环境中使用udp套接字。我目前正在使用标准套接字函数sendto(),这需要相当多的时间。我读过可以使用零拷贝,如果我理解的话,可以避免通过从用户/内核环境复制文件来增加额外的时间。但是,我看到sendfile()只允许从一个文件描述符复制到另一个文件描述符。我无法看到如何使用它来发送UDP数据包,在我的情况下是一个缓冲区。所以我的问题是:

  1. 甚至可以使用sendfile()发送UDP数据包吗?
  2. 如果是这样,这样做的正确方法是什么?
  3. 修改

    我正在一个实时平台上工作,我有几个操作加上通过套接字发送。所有这些都不应超过1毫秒。我尝试了三台机器,第一台机器有4核,频率为3.4GHz,另外8核,频率为2.3GHz,最后一台是4核,频率为1.4GHz。在第一个上,发送一个720字节的数据包需要不到1μs。而另外两个则介于6到9μs之间。我正在使用Linux低延迟内核,并取消激活所有CPU电源管理功能,因此所有CPU都处于最大频率。

    我注意到如果sendto()所花费的时间大于6μs,那么平台根本不起作用。另一个精度,我有几个并行运行的线程。所以也许只是CPU处理其他线程而sendto()还没有完成。我想知道这是可能的,在进行其他操作时停止sendto()。

    这就是为什么我试图找到其他解决方案在其他地方进行优化,我认为使用sendfile()可以避免额外的时间被保存。

1 个答案:

答案 0 :(得分:0)

我不确定sendfile是否适用于UDP套接字,但是,memfd_create从内存创建文件描述符,理论上可以绕过从用户空间到内核的复制。

但是,当发送内核时,必须首先将数据复制到内核套接字缓冲区中,因为它需要在UDP,IP和以太网报头之前添加用户数据,这是无法就地完成的。即使使用sendfile,也无法避免此复制。

要进行真正的零拷贝网络,您可以查看PF_RING ZC (Zero Copy)驱动程序:

  

使用PF_RING Aware驱动程序的按需内核旁路

     

PF_RING™ZC附带新一代PF_RING™感知驱动程序,可在内核或旁路模式下使用。安装后,驱动程序作为标准Linux驱动程序运行,您可以在其中进行正常的网络连接(例如ping或SSH)。当从PF_RING™使用时,它们比香草驱动器更快,因为它们直接与它相互作用。如果使用零拷贝中的PF_RING感知驱动程序打开设备(例如pfcount -i zc:eth1),则设备将无法用于标准网络,因为它通过内核旁路以零拷贝方式访问,就像之前的DNA一样。关闭访问设备的应用程序后,可以再次进行标准网络活动。