c - 以微秒级精度接收 RAW 套接字数据包

标签 c linux performance sockets networking

我正在编写一个代码,它每 1 毫秒从服务器接收一次原始以太网数据包(无 TCP/UDP)。对于收到的每个数据包,我的应用程序必须回复 14 个原始数据包。如果服务器在按计划每 1 毫秒发送一次数据包之前未收到 14 个数据包,则服务器会发出警报并且应用程序必须中断。服务器-客户端通信是一对一的链接。

服务器是一个硬件(FPGA),它以精确的 1ms 间隔生成数据包。客户端应用程序在具有 10G SolarFlare NIC 的 Linux (RHEL/Centos 7) 机器上运行。

我的第一版代码是这样的

while(1)
{
  while(1)
  {
     numbytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
     if(numbytes > 0)
     {
        //Some more lines here, to read packet number
        break;
     }
  }
  for (i=0;i<14;i++)
  {
     if (sendto(sockfd,(void *)(sym) , sizeof(sym), 0, NULL, NULL) < 0)
            perror("Send failed\n");
  }
}

我通过在 recvfrom 调用之前和之后的时间戳(使用 clock_gettime)测量接收时间,我打印这些时间戳的时间差并在任何时候打印它们时差超过900-1100 us的允许范围。

我面临的问题是数据包接收时间在波动。像这样(打印以微秒为单位)

Decode Time : 1234
Decode Time : 762
Decode Time : 1593
Decode Time : 406
Decode Time : 1703
Decode Time : 257
Decode Time : 1493
Decode Time : 514
and so on..

有时解码时间超过 2000us,应用程序会崩溃。

在这种情况下,应用程序会中断 2 秒到几分钟。

到目前为止我尝试过的选项。

  1. 设置与特定隔离核心的亲和力。
  2. 使用 SCHED_FIFO 将调度优先级设置为最大
  3. 增加套接字缓冲区大小
  4. 将网络接口(interface)中断关联设置为处理应用程序的同一核心
  5. 使用 poll(),select() 调用旋转 recvfrom

所有这些选项都比初始版本的代码有了显着改进。现在应用程序将运行约 1-2 小时。但这还不够。

一些观察:

  1. 每当我在应用程序运行时对 Linux 机器进行 ssh session 时,我都会得到这些解码时间打印的大量转储(这让我认为通过其他 1G 以太网接口(interface)进行的网络通信正在对 10G 以太网接口(interface)产生干扰)。
  2. 该应用程序在 RHEL(运行时间约 2-3 小时)中的性能优于 Centos(运行时间约 30 分钟 - 1.5 小时)
  3. 运行时间也因具有不同硬件配置和相同操作系统的 Linux 机器而异。

如果有任何其他方法可以提高应用程序的运行时间,请提出建议。

提前致谢。

最佳答案

首先需要验证时间戳方法的准确性; clock_gettime。分辨率是纳秒级,但是准确度和精密度有问题。这不是您问题的答案,但会在继续之前告知时间戳的可靠性。参见 Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?为什么 CLOCK_MONOTONIC 应该用于您的应用程序。

我怀疑大部分解码时间波动是由于每次解码的操作数量可变、操作系统的上下文切换或 IRQ。

每次解码的操作我无法评论,因为代码已在您的帖子中得到简化。也可以分析和检查此问题。

可以轻松检查和监控每个进程的上下文切换 https://unix.stackexchange.com/a/84345

正如 Ron 所说,这些是对网络的非常严格的时序要求。它必须是一个孤立的网络,并且只有一个目的。当 ssh'ing 表明必须阻止所有其他流量时,您对解码超时的观察。考虑到单独的 NIC,这令人不安。因此我怀疑 IRQ 是问题所在。参见/proc/interrupts。

要在很长的时间间隔(小时 -> 天)内实现一致的解码时间,需要大幅简化操作系统。删除不必要的进程和服务、硬件,并可能构建您自己的内核。一切都是为了减少上下文切换和中断的目标。此时应考虑实时操作系统。这只会提高解码时间一致的概率,并不能保证。

我的工作是开发一个结合了 FPGA ADC、PC 和以太网的数据采集系统。不可避免地,多用途 PC 的不一致性意味着某些功能必须转移到专用硬件上。考虑为 PC 开发应用程序与将其转移到硬件上的优缺点。

关于c - 以微秒级精度接收 RAW 套接字数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35357567/

相关文章:

C反向shell问题

c - 作为 const 或操作数的正确参数

Python 脚本不在 cron 作业中执行 bash 命令

python - 为什么在 Windows 上导入某些 SciPy 模块需要这么长时间?

python - Python 中内置方法中嵌套模块的大 O 表示法

c++ - realloc C 函数的可能包装函数有什么错误?

c - int bitparity的解释

linux - 每个版本都会下载 Yocto zip

linux - linux下找不到别人的主目录

c# - Resolve在Unity中的性能和使用