2009-07-19 14 views
78

बीएसडी सॉकेट प्रोग्रामिंग के संदर्भ में मैं प्रत्येक उदाहरण और चर्चा में भाग लेता हूं, ऐसा लगता है कि फ़ाइल डिस्क्रिप्टर को I/O मोड को अनब्लॉक करने के लिए अनुशंसित तरीका O_NONBLOCK का उपयोग कर रहा है fcntl() पर ध्वज, उदाहरण के लिएयूनिक्स नॉनब्लॉकिंग I/O: O_NONBLOCK बनाम FIONBIO

int flags = fcntl(fd, F_GETFL, 0); 
fcntl(fd, F_SETFL, flags | O_NONBLOCK); 

मैं दस साल के लिए UNIX में नेटवर्क प्रोग्रामिंग कर दिया गया है, और हमेशा FIONBIO ioctl() कॉल का इस्तेमाल किया है यह करने के लिए:

int opt = 1; 
ioctl(fd, FIONBIO, &opt); 

कभी वास्तव में क्यों पर बहुत विचार दे दी है। बस इसे इस तरह से सीखा।

क्या किसी के पास एक या दूसरे के संभावित संबंधित गुणों पर कोई टिप्पणी है? मुझे लगता है कि पोर्टेबिलिटी लोकस कुछ हद तक अलग है, लेकिन यह नहीं पता कि ioctl_list(2) किस हद तक व्यक्तिगत ioctl विधियों के उस पहलू से बात नहीं करता है।

उत्तर

114

मानकीकरण से पहले वहाँ ioctl( था। .. FIONBIO ... ) और fcntl( ... O_NDELAY ... ), लेकिन ये सिस्टम के बीच असंगत रूप से व्यवहार करते थे, और यहां तक ​​कि उसी प्रणाली के भीतर भी। उदाहरण के लिए, FIONBIO के लिए सॉकेट और O_NDELAY पर काम करने के लिए यह सामान्य था, जिसमें पाइप, फीफो और डिवाइस जैसी चीजों के लिए असंगतता थी। और यदि आपको नहीं पता था कि आपके पास किस तरह का फ़ाइल डिस्क्रिप्टर था, तो आपको यह सुनिश्चित करने के लिए दोनों सेट करना होगा। लेकिन इसके अलावा, उपलब्ध डेटा के साथ एक गैर-अवरुद्ध पढ़ने को भी असंगत रूप से इंगित किया गया था; ओएस और फाइल डिस्क्रिप्टर के प्रकार के आधार पर पढ़ा 0, या -1 इरनो ईजेन के साथ, या -1 त्रुटि इडौल्डब्लॉक के साथ वापस आ सकता है। आज भी, सोलारिस पर FIONBIO या O_NDELAY सेट करने से कोई डेटा नहीं होता है, जिसमें किसी डेटा को टीटी या पाइप पर 0 लौटाया जाता है, या -1 सॉकेट पर इग्नो ईजेन के साथ होता है। हालांकि 0 संदिग्ध है क्योंकि यह ईओएफ के लिए भी वापस आ गया है।

POSIX ने O_NONBLOCK की शुरुआत के साथ इसे संबोधित किया, जिसमें विभिन्न प्रणालियों और फ़ाइल डिस्क्रिप्टर प्रकारों के मानकीकृत व्यवहार हैं। चूंकि मौजूदा सिस्टम आमतौर पर व्यवहार में किसी भी बदलाव से बचना चाहते हैं जो पिछड़े संगतता को तोड़ सकता है, POSIX ने दूसरों में से एक के लिए विशिष्ट व्यवहार को अनिवार्य करने के बजाय एक नया झंडा परिभाषित किया है। लिनक्स जैसी कुछ प्रणालियों में सभी 3 समान व्यवहार करते हैं, और ईगैन और ईवॉल्डब्लॉक को एक ही मूल्य पर परिभाषित करते हैं, लेकिन पिछड़े संगतता के लिए कुछ अन्य विरासत व्यवहार को बनाए रखने की इच्छा रखने वाले सिस्टम ऐसा कर सकते हैं जब पुराने तंत्र का उपयोग किया जाता है।

नए कार्यक्रमों को fcntl( का उपयोग करना चाहिए ... O_NONBLOCK ... ), जैसा कि पॉज़िक्स द्वारा मानकीकृत किया गया है।

+5

मैं इसके लिए ioctl() का उपयोग करता हूं क्योंकि यह मुझे केवल एक सिस्कोल खर्च करता है ताकि fcntl() के लिए दो के बजाय गैर-अवरोधन मोड सक्षम किया जा सके। इसके अतिरिक्त, Windows ioctlsocket() API इस कार्यक्षमता के प्रयोजनों के लिए ioctl() के बराबर है। –

+0

nginx यह कर सकता है अगर यह कर सकता है, और इसे एक टिप्पणी के साथ चिह्नित करता है "ioctl (FIONBIO) एकल सिस्कल के साथ एक गैर-अवरोधन मोड सेट करता है।" अब स्वीकार्य 2 है जो आपको एक कनेक्शन स्वीकार करने देता है और इसे उसी सिस्कोल में गैर-अवरुद्ध मोड में डाल देता है। – Eloff

5

मुझे विश्वास है कि fcntl() एक पॉज़िक्स फ़ंक्शन है। जहां ioctl() एक मानक यूनिक्स चीज है। यहां POSIX io की एक सूची दी गई है। ioctl() एक बहुत ही कर्नेल/ड्राइवर/ओएस विशिष्ट चीज है, लेकिन मुझे यकीन है कि यूनिक्स के अधिकांश स्वादों पर आप क्या काम करते हैं। कुछ अन्य ioctl() सामान केवल कुछ ओएस या इसके कर्नेल के कुछ संशोधनों पर ही काम कर सकते हैं।

+0

मैंने एआईक्स, सोलारिस, लिनक्स, * बीएसडी, और आईआरईएक्स पर कोई समस्या नहीं के साथ FIONBIO का उपयोग किया है। लेकिन हाँ, मैं समझता हूं कि यह विंडोज पर काम नहीं करेगा, उदाहरण के लिए - यह एक बहुत ही विशिष्ट कर्नेल कार्यान्वयन के लिए एक निम्न स्तरीय इंटरफ़ेस है। फिर भी, मुझे आश्चर्य है कि क्या कोई अन्य अंतरकारी कारक हैं। –

4

जैसा कि @ सेन ने कहा, fcntl() काफी हद तक मानकीकृत है, और इसलिए प्लेटफॉर्म पर उपलब्ध है। ioctl() फ़ंक्शन यूनिक्स में fcntl() से पूर्व निर्धारित करता है, लेकिन यह बिल्कुल मानकीकृत नहीं है। ioctl() आपके लिए प्रासंगिकता के सभी प्लेटफॉर्म पर आपके लिए काम करता है, लेकिन भाग्यशाली नहीं है। विशेष रूप से, दूसरे तर्क के लिए उपयोग किए गए नाम आर्केन हैं और प्लेटफॉर्म पर भरोसेमंद नहीं हैं। दरअसल, वे विशेष डिवाइस ड्राइवर के लिए अनूठे होते हैं जो फाइल डिस्क्रिप्टर संदर्भ। (ioctl() कॉल, थोड़ा-मैप किया ग्राफिक्स बीस साल पहले कुछ और कहीं और करने के लिए अनुवाद कभी नहीं की) एक आईसीएल Perq पर चल रहे डिवाइस PNX (Perq यूनिक्स चलाने के लिए इस्तेमाल किया, उदाहरण के लिए।)

संबंधित मुद्दे