8

QNX Neutrino マシンに 819.2 Hz (~1.2ms) の速度で UDP パケットを送信するソースがあります。これらのメッセージをできるだけ遅延やジッターを少なくして受信し、処理したいと考えています。

私の最初のコードは基本的に次のとおりです。

SetupUDPSocket(); 
while (true) {
    recv(socket, buffer, BufferSize, MSG_WAITALL); // blocks until whole packet is received
    processPacket(buffer);
}

問題は、recv() が、システムの各タイマー ティックで、利用可能な新しいパケットがあるかどうかのみをチェックすることです。タイマーティックは通常 1ms です。したがって、これを使用すると、1 ミリ秒ごとまたは 2 ミリ秒ごとにパケットを処理するため、大きなジッターが発生します。タイマーの目盛りのサイズをリセットすることはできますが、それはシステム全体 (および他のプロセスの他のタイマーなど) に影響します。819.2 Hz と正確に一致することは絶対にないので、それでもジッターが発生します。

ということで、ネットワークカードの割り込み線を使ってみました(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;
} 

これにより、最初に 1 回の読み取りが成功し、その後 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

読んでくれてありがとう!

4

4 に答える 4

1

「問題は、recv()がシステムの各タイマーティックで新しいパケットが利用可能かどうかをチェックするだけであるということです。タイマーティックは通常1msです。」というステートメントの理由はよくわかりません。プリエンプティブOSに当てはまります。システム構成に何かがある必要があります。そうでない場合、ネットワークプロトコルスタックの実装にいくつかの問題があります。

数年前、Yahoo BBJapanのIPTVSTBプロジェクトに取り組んでいたときに、RTP受信で問題が発生しました。問題は遅延やジッターではなく、NDSアルゴリズムを追加した後のSTBの全体的なシステムパフォーマンスです。vxWorksを使用しており、vxWorksはイーサネットフックインターフェイスをサポートしています。これは、ドライバーがイーサネットパケットを受信するたびに呼び出されます。

APIをフックして、イーサネットパケットから指定されたポートでUDPを直接解析します。もちろん、断片化がないという仮定もあります。これは、パフォーマンスの問題に対するネットワーク設定によって保証されています。たぶん、QNXイーサネットドライバで同じフックを取得できるかどうかを確認することもできます。少なくとも、ジッターがドライバーに起因するかどうかがわかりました。

于 2013-02-27T05:30:23.867 に答える
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()を使用して、使用する信号処理関数をOSに指示します。あなたの場合、シグナルハンドラーはソケットからデータを読み取り、処理のためにバッファーに保存することができます。pause()を使用して、SIGIO信号を処理するまでプロセスを一時停止します。シグナルハンドラーが戻ると、プロセスがウェイクアップし、バッファー内のデータを処理できます。これにより、タイマーやハードウェア割り込みを処理しなくても、データが入ってくるときにデータを処理できるようになります。注意すべきことの1つは、UDPトラフィックが着信するのと同じ速さでシステムがこれらの信号を処理できることです。

于 2013-03-20T04:06:07.710 に答える
0

UDPパケットの大きさはどれくらいですか?パケットサイズが小さい場合は、より多くのデータを1つのパケットにパックし、伝送速度を下げることで、効率を高めることができます。

于 2012-09-07T09:48:09.810 に答える
0

割り込みサービス ルーティング (ISR) が割り込みをマスクしていないと思われます。おそらく、エッジセンシティブに設計されており、割り込みはレベルセンシティブです。

于 2012-10-09T22:22:24.940 に答える