2012-08-08 152 views
8

我有一個以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 

感謝您的閱讀!

+1

'問題是recv()僅在系統的每個計時器滴答時檢查是否有新的數據包可用' - 爲什麼會這樣做?我不知道任何QNX, - 網絡驅動程序不能正常工作嗎?中斷驅動程序應該設置一個事件/信號量並通過操作系統退出,這樣就可以立即設置recv()線程。應該不需要任何「等到計時器打勾」 - 這是無望的 - 也可以使用協作輪詢循環:( – 2012-08-08 16:44:39

+0

像Martin提到的實現細節可能因驅動程序和卡的特定型號而異,但您沒有 – 2012-08-08 17:12:04

+0

@MartinJames和Ben Voigt:對不起,我沒有意識到我的問題可能與驅動程序有關,'nicinfo'表示「INTEL 82544千兆位(銅纜)以太網控制器」和「pci -vvv」輸出「供應商ID = 8086h,英特爾公司 設備ID = 107ch,82541PI千兆位以太網控制器「 – jan 2012-08-09 10:46:31

回答

0

你的UDP數據包有多大?如果數據包的大小很小,您將通過將更多的數據包裝到單個數據包中並降低傳輸速率來獲得更高的效率。

0

我懷疑中斷服務路由(ISR)沒有屏蔽中斷。也許它是爲邊緣敏感而設計的,中斷是電平敏感的。

1

我很不清楚爲什麼聲明「問題是recv()只在系統的每個計時器滴答時檢查是否有新的數據包可用,計時器滴答通常爲1ms。對於先發制人的操作系統,將是真實的。系統配置中必須有一些東西,或者網絡協議棧實現有一些問題。

幾年前,當我在爲雅虎BB日本公司工作一些IPTV STB項目時,我在RTP接收中遇到了問題。問題不在於延遲或抖動,而在於我們添加了一些NDS算法後STB的整體系統性能。我們使用vxWorks,並且vxWorks支持以太網鉤子接口,每次驅動程序接收到以太網數據包時都會調用它。

我掛接一個API到它,並直接解析UDP從指定的端口從以太網數據包直接。當然,我們有一些假設,沒有碎片,這是由性能問題的網絡設置保證。也許你也可以檢查一下,看你是否可以在QNX以太網驅動程序中獲得相同的鉤子。至少你發現如果抖動來自司機或不。

0

對不起,我晚了一點,但我遇到了你的問題,看到它與我遇到的情況類似。除了硬件中斷之外,您可以嘗試使用信號進行軟件中斷。 QNX在這裏有一些文檔:http://www.qnx.com/developers/docs/qnx_4.25_docs/qnx4/sysarch/microkernel.html#IPCSIGNALS。我當時使用CentOS,但理論是一樣的。根據http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/lib_ref/s/socket.html,您可以使用ioctl()爲給定文件描述符的SIGIO信號設置一個接收組...在您的情況下是一個UDP套接字。當套接字有數據準備好讀取時,SIGIO信號被髮送到由ioctl()指示的進程。使用sigaction()告訴操作系統使用什麼信號處理函數。就你而言,信號處理程序可以從套接字讀取數據並將其存儲在緩衝區中進行處理。使用pause()暫停進程,直到它處理SIGIO信號。當信號處理程序返回時,進程將會喚醒,您可以處理緩衝區中的數據。 這應該允許您在處理數據時無需處理定時器或硬件中斷。有一點需要注意的是,您的系統可以像UDP流量進入一樣快地處理這些信號。