我有一个以819.2Hz(〜1.2ms)的速率向我的QNX Neutrino机器发送UDP数据包的源。我想以尽可能小的延迟和抖动来接收和处理这些消息。使用QNX RTOS实时接收UDP数据包
我的第一代码基本上是:
SetupUDPSocket();
while (true) {
recv(socket, buffer, BufferSize, MSG_WAITALL); // blocks until whole packet is received
processPacket(buffer);
}
的问题是,的recv()仅在系统的每个计时器滴答检查是否有可用的新的分组。计时器刻度通常为1ms。所以,如果我使用这个,我会得到一个巨大的抖动,因为我每隔1ms或每2ms处理一个数据包。我可以重置计时器滴答的大小,但这会影响整个系统(以及其他进程的其他定时器等)。而且我仍然会有抖动,因为我绝对不会完全匹配819.2赫兹。
所以,我试图使用网卡(5)的中断线。但是,似乎也有其他的事情导致中断上升。我以前的代码如下:
ThreadCtl(_NTO_TCTL_IO, 0);
SIGEV_INTR_INIT(&event);
iID = InterruptAttachEvent(IRQ5, &event, _NTO_INTR_FLAGS_TRK_MSK);
while(true) {
if (InterruptWait(0, NULL) == -1) {
std::cerr << "errno: " << errno << std::endl;
}
length = recv(socket, buffer, bufferSize, 0); // non-blocking this time
LogTimeAndLength();
InterruptUnmask(IRQ5, iID;
}
这会导致一次成功的读取,然后在0时间过后读取0字节长度的数据。看起来,在执行完InterruptUnmask()后,InterruptWait()根本不会等待,所以必须有一个新的中断(或相同的?!)。
是否有可能做这样的事情与网卡的中断线?是否有其他可能性以819.2 Hz的速率接收数据包?
关于网卡的一些信息: 'PCI -vvv' 输出:
Class = Network (Ethernet)
Vendor ID = 8086h, Intel Corporation
Device ID = 107ch, 82541PI Gigabit Ethernet Controller
PCI index = 0h
Class Codes = 020000h
Revision ID = 5h
Bus number = 4
Device number = 15
Function num = 0
Status Reg = 230h
Command Reg = 17h
I/O space access enabled
Memory space access enabled
Bus Master enabled
Special Cycle operations ignored
Memory Write and Invalidate enabled
Palette Snooping disabled
Parity Error Response disabled
Data/Address stepping disabled
SERR# driver disabled
Fast back-to-back transactions to different agents disabled
Header type = 0h Single-function
BIST = 0h Build-in-self-test not supported
Latency Timer = 40h
Cache Line Size= 8h un-cacheable
PCI Mem Address = febc0000h 32bit length 131072 enabled
PCI Mem Address = feba0000h 32bit length 131072 enabled
PCI IO Address = ec00h length 64 enabled
Subsystem Vendor ID = 8086h
Subsystem ID = 1376h
PCI Expansion ROM = feb80000h length 131072 disabled
Max Lat = 0ns
Min Gnt = 255ns
PCI Int Pin = INT A
Interrupt line = 5
CPU Interrupt = 5h
Capabilities Pointer = dch
Capability ID = 1h - Power Management
Capabilities = c822h - 28002000h
Capability ID = 7h - PCI-X
Capabilities = 2h - 400000h
Device Dependent Registers:
0x040: 0000 0000 0000 0000 0000 0000 0000 0000
...
0x0d0: 0000 0000 0000 0000 0000 0000 01e4 22c8
0x0e0: 0020 0028 0700 0200 0000 4000 0000 0000
0x0f0: 0500 8000 0000 0000 0000 0000 0000 0000
和 'nicinfo' 输出:
wm1:
INTEL 82544 Gigabit (Copper) Ethernet Controller
Physical Node ID ........................... 000E0C C5F6DD
Current Physical Node ID ................... 000E0C C5F6DD
Current Operation Rate ..................... 100.00 Mb/s full-duplex
Active Interface Type ...................... MII
Active PHY address ....................... 0
Maximum Transmittable data Unit ............ 1500
Maximum Receivable data Unit ............... 0
Hardware Interrupt ......................... 0x5
Memory Aperture ............................ 0xfebc0000 - 0xfebdffff
Promiscuous Mode ........................... Off
Multicast Support .......................... Enabled
感谢您的阅读!
'问题是recv()仅在系统的每个计时器滴答时检查是否有新的数据包可用' - 为什么会这样做?我不知道任何QNX, - 网络驱动程序不能正常工作吗?中断驱动程序应该设置一个事件/信号量并通过操作系统退出,这样就可以立即设置recv()线程。应该不需要任何“等到计时器打勾” - 这是无望的 - 也可以使用协作轮询循环:( – 2012-08-08 16:44:39
像Martin提到的实现细节可能因驱动程序和卡的特定型号而异,但您没有 – 2012-08-08 17:12:04
@MartinJames和Ben Voigt:对不起,我没有意识到我的问题可能与驱动程序有关,'nicinfo'表示“INTEL 82544千兆位(铜缆)以太网控制器”和“pci -vvv”输出“供应商ID = 8086h,英特尔公司 设备ID = 107ch,82541PI千兆位以太网控制器“ – jan 2012-08-09 10:46:31