2012-08-08 52 views
8

के साथ यूडीपी पैकेट का रीयलटाइम प्राप्त करना मेरे पास एक स्रोत है जो मेरी क्यूएनएक्स न्यूट्रीनो मशीन पर 819.2 हर्ट्ज (~ 1.2 एमएमएस) की दर से यूडीपी पैकेट भेजता है। मैं उन संदेशों को जितना संभव हो उतना देरी और जिटर के साथ प्राप्त करना और संसाधित करना चाहता हूं।क्यूएनएक्स आरटीओएस

मेरा पहला कोड मूल रूप से किया गया था:

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 हर्ट्ज की दर से पैकेट प्राप्त करने के लिए कोई अन्य संभावनाएं हैं?

नेटवर्क कार्ड के बारे में कुछ जानकारी: 'पीसीआई -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() केवल एक नया पैकेट होने पर सिस्टम के प्रत्येक टाइमर टिक पर जांचता है उपलब्ध '- ऐसा क्यों होगा? मुझे कोई क्यूएनएक्स नहीं पता, - क्या नेटवर्क चालक सैनि से काम नहीं करता है? इंटरप्ट ड्राइवर को एक ईवेंट/सेमफोर सेट करना चाहिए और ओएस के माध्यम से बाहर निकलना चाहिए ताकि यह recv() थ्रेड को 'तत्काल' तैयार कर सके। किसी भी 'टाइमर टिक तक प्रतीक्षा करें' की आवश्यकता नहीं होनी चाहिए - यह सिर्फ निराशाजनक है - साथ ही सहकारी मतदान लूप का भी उपयोग कर सकता है :( –

+0

मार्टिन जैसे कार्यान्वयन विवरण ड्राइवर और यहां तक ​​कि कार्ड के विशिष्ट मॉडल के साथ भिन्न हो सकते हैं, लेकिन आपने नहीं किया है सूचीबद्ध या तो –

+0

@ मार्टिनजेम्स और बेन वोगेट: क्षमा करें, मुझे इस तथ्य से अवगत नहीं था कि मेरी समस्या ड्राइवर से संबंधित हो सकती है। 'निकिनोफो' का कहना है, "इंटेल 82544 गिगाबिट (कॉपर) ईथरनेट कंट्रोलर" और 'पीसीआई-वीवीवी' आउटपुट " विक्रेता आईडी = 8086 एच, इंटेल कॉर्पोरेशन डिवाइस आईडी = 107ch, 82541PI गिगाबिट ईथरनेट कंट्रोलर " – jan

उत्तर

0

आपके यूडीपी पैकेट कितने बड़े हैं? यदि पैकेट आकार छोटा है तो आपको अधिक डेटा को एकल पैकेट में पैक करके और ट्रांसमिशन दर घटाने से अधिक दक्षता प्राप्त होगी।

0

मुझे संदेह है कि इंटरप्ट सेवा रूटिंग (आईएसआर) बाधा डालने वाला नहीं है। शायद यह एज-संवेदनशीलता के लिए डिज़ाइन किया गया है और बाधा स्तर-संवेदनशील है।

1

मुझे यकीन नहीं है कि कथन क्यों है "समस्या यह है कि recv() केवल एक नया पैकेट उपलब्ध होने पर सिस्टम के प्रत्येक टाइमर टिक पर जांचता है। टाइमर टिक आमतौर पर 1ms है।" प्रीपेप्टिव ओएस के लिए सच होगा। सिस्टम कॉन्फ़िगरेशन में कुछ होना चाहिए या नेटवर्क प्रोटोकॉल स्टैक कार्यान्वयन में कुछ समस्याएं हैं।

साल पहले जब मैं याहू बीबी जापान के लिए कुछ आईपीटीवी एसटीबी परियोजना पर काम कर रहा था, मुझे आरटीपी प्राप्त करने में कोई समस्या मिली। मुद्दों में देरी या जिटर नहीं है, लेकिन कुछ एनडीएस एल्गोरिदम जोड़ने के बाद एसटीबी में समग्र सिस्टम प्रदर्शन। हम vxWorks का उपयोग कर रहे हैं, और vxWorks समर्थन ईथरनेट हुक इंटरफ़ेस, जिसे हर बार ड्राइवर द्वारा प्राप्त ईथरनेट पैकेट प्राप्त किया जाएगा।

मैं इसमें एक एपीआई लगाता हूं और सीधे ईथरनेट पैकेट से निर्दिष्ट बंदरगाह के साथ यूडीपी को पार्स करता हूं। बेशक हमारे पास कुछ धारणा है कि कोई विखंडन नहीं है, जिसे प्रदर्शन समस्याओं के लिए नेटवर्क सेटअप द्वारा गारंटी दी जाती है। हो सकता है कि आप यह देखने के लिए भी जांच कर सकें कि क्या आप क्यूएनएक्स ईथरनेट ड्राइवर में एक ही हुक प्राप्त कर सकते हैं। पट्टे पर आपको पता चला कि जिटर ड्राइवर से आता है या नहीं।

0

क्षमा करें, मैं पार्टी के लिए थोड़ा देर हो चुकी हूं, लेकिन मैं आपके प्रश्न पर आया और देखा कि यह एक ऐसी स्थिति के समान था जो मुझे सामना करना पड़ा। हार्डवेयर इंटरप्ट्स के बजाय, आप संकेतों का उपयोग कर सॉफ़्टवेयर बाधित करने का प्रयास कर सकते हैं। क्यूएनएक्स में यहां कुछ दस्तावेज हैं: http://www.qnx.com/developers/docs/qnx_4.25_docs/qnx4/sysarch/microkernel.html#IPCSIGNALS। मैं उस समय सेंटोस का उपयोग कर रहा था लेकिन सिद्धांत वही है। http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/lib_ref/s/socket.html के अनुसार आप किसी दिए गए फ़ाइल डिस्क्रिप्टर के लिए SIGIO सिग्नल के लिए प्राप्त समूह सेट अप करने के लिए ioctl() का उपयोग कर सकते हैं ... आपके मामले में एक यूडीपी सॉकेट। जब सॉकेट में डेटा पढ़ने के लिए तैयार होता है, तो SIOIO सिग्नल ioctl() द्वारा संकेतित प्रक्रिया को भेजा जाता है। ओएस को बताने के लिए सिग्नल हैंडलिंग फ़ंक्शन का उपयोग करने के लिए सिग्नेशन() का उपयोग करें। आपके मामले में, सिग्नल हैंडलर सॉकेट से डेटा को पढ़ सकता है और प्रोसेसिंग के लिए इसे बफर में स्टोर कर सकता है। जब तक यह सिगियो सिग्नल को संभाल नहीं लेता तब तक प्रक्रिया को निलंबित करने के लिए रोकें() का उपयोग करें। जब सिग्नल हैंडलर लौटाता है, तो प्रक्रिया जागृत हो जाएगी और आप बफर में डेटा को संसाधित कर सकते हैं। आपको टाइमर या हार्डवेयर इंटरप्ट से निपटने के बिना आपके डेटा को संसाधित करने की अनुमति देनी चाहिए। एक बात यह जानना है कि आपका सिस्टम उन संकेतों को तेज़ी से संसाधित कर सकता है जैसे यूडीपी यातायात आ रहा है।