[英]Receiving RAW socket packets with microseconds level accuracy
我正在编写一个代码,它从服务器每1ms接收一次原始以太网数据包(无TCP / UDP)。 对于收到的每个数据包,我的应用程序必须回复14个原始数据包。 如果服务器在每1ms发送一次数据包之前没有收到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秒到几分钟之间的任何地方中断。
我试过的选项到现在为止。
SCHED_FIFO
将调度优先级设置为最大值 poll(),select()
调用在recvfrom
旋转。 所有这些选项都比初始版本的代码有了显着的改进。 现在应用程序将运行约1-2个小时。 但这仍然不够。
一些观察:
请提示是否有其他方法可以改善应用程序的运行时间。
提前致谢。
首先,您需要验证时间戳方法的准确性; clock_gettime。 分辨率为纳秒,但精度和精度都存在问题。 这不是您的问题的答案,但在继续之前告知时间戳的可靠性。 请参阅CLOCK_REALTIME和CLOCK_MONOTONIC之间的区别? 为什么CLOCK_MONOTONIC应该用于您的应用程序。
我怀疑大部分解码时间波动是由于每个解码的操作数量可变,操作系统的上下文切换或IRQ。
每个解码操作我无法评论,因为您的帖子中的代码已经简化。 此问题也可以进行分析和检查。
可以轻松检查和监控每个进程的上下文切换https://unix.stackexchange.com/a/84345
正如Ron所说,这些是对网络非常严格的时序要求。 它必须是一个孤立的网络,并且是单一的目的。 当ssh'ing指示所有其他流量时,您对解码超时的观察必须被阻止。 考虑到单独的NIC,这是令人不安的。 因此我怀疑IRQ是个问题。 请参阅/ proc / interrupts。
要在较长的时间间隔(小时 - >天)内实现一致的解码时间,需要大幅简化操作系统。 删除不必要的进程和服务,硬件,并可能构建自己的内核。 所有这些都是为了减少上下文切换和中断。 此时应考虑实时操作系统。 这只会提高解码时间一致的概率,而不是保证。
我的工作是开发一个数据采集系统,它是FPGA ADC,PC和以太网的组合。 不可避免地,多功能PC的不一致意味着某些功能必须转移到专用硬件。 考虑开发PC应用程序与将其移至硬件的优点/缺点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.