2012-09-09 23 views
35

मेरे पास एक वैरिएबल कहते हैं var में एक फ़ाइल डिस्क्रिप्टर संग्रहित है। मैं कैसे जांच सकता हूं कि वह वर्णनकर्ता बाद के चरण में मान्य है या नहीं?कैसे जांचें कि एक चर में संग्रहीत एक दिया गया फ़ाइल डिस्क्रिप्टर अभी भी वैध है या नहीं?

fdvar1= open(.....); 
    fdvar2 = fdvar1;  // Please ignore the bad design 

    .... 
    // lots of loops , conditionals and threads. It can call close(fdvar2) also. 
    .... 

    if(CheckValid(fdvar1)) // How can I do this check ? 
    write(fdvar1, ....); 

अब मैं यह जांचना चाहता हूं कि var1 (जो अभी भी खोला गया वर्णनकर्ता है) अभी भी मान्य है। इसके लिए कोई एपीआई है?

+2

क्यों एफडी सी स्तर के बजाय ओएस स्तर पर नकल की जाती है? –

+1

['dup'] (http://linux.die.net/man/2/dup) के लिए मैन्युअल पृष्ठ देखें। –

+2

भले ही आप वैधता की जांच कर सकें, परिणाम अधिकतर बेकार है, क्योंकि यह संभव है कि मूल बंद होने के बाद एक और खुली फ़ाइल को वही वर्णक प्राप्त हो। – interjay

उत्तर

58

fcntl(fd, F_GETFD) कि fd एक वैध फ़ाइल खोलने की जानकारी देता है की जाँच करने के विहित सबसे सस्ता तरीका है। यदि आपको शून्य समय के साथ poll का उपयोग करके सदस्य 0 पर सेट किया गया है और revents में लौटने के बाद यह अधिक कुशल है, तो आपको बैच-चेक करने की आवश्यकता है।

इसके साथ, ऑपरेशन "जांचें कि कोई दिया गया संसाधन हैंडल अभी भी वैध है" लगभग हमेशा मौलिक रूप से गलत है। संसाधन संभाल मुक्त होने के बाद (उदा। एक एफडी close डी) है, इसके मूल्य को आपके द्वारा आवंटित अगले ऐसे संसाधन को फिर से सौंप दिया जा सकता है। यदि किसी भी शेष संदर्भ का उपयोग किया जा सकता है, तो वे गलत तरीके से नए संसाधन पर गलत तरीके से काम करेंगे। इस प्रकार, वास्तविक उत्तर शायद है: यदि आप अपने कार्यक्रम के तर्क से पहले से ही नहीं जानते हैं, तो आपके पास प्रमुख मौलिक तर्क त्रुटियां हैं जिन्हें ठीक करने की आवश्यकता है।

+1

@R मान लीजिए कि मैं एक पुस्तकालय को लागू करने की कोशिश कर रहा हूं जो एक एफडी को संभालता है, उदाहरण के लिए पाइप लाइब्रेरी, और मैं वह हूं जो एफडी तर्कों को उन कार्यक्रमों में पास करता है जो मेरी लाइब्रेरी का उपयोग करेंगे, यह अभी भी एफडी के परीक्षण के लिए खराब अभ्यास है मान्यता? या यह अनिवार्य है? – petric

+0

@petric: मुझे आपका प्रश्न समझ में नहीं आता है। एक सामान्य उत्तर के रूप में, मैं हाँ कहने जा रहा हूं, यह "एफडी सत्यापन के लिए परीक्षण" करने के लिए बुरा (और अर्थहीन) है, लेकिन यदि आप जो कर रहे हैं उसके बारे में आपको विशेष चिंताएं हैं तो आपको शायद इसके बारे में पूछने के लिए एक नया प्रश्न पोस्ट करना चाहिए (और एक टिप्पणी में पूछने के बजाय इस प्रश्न/उत्तर का जिक्र करते हुए)। –

21

आप fcntl() फ़ंक्शन का उपयोग कर सकते हैं:

int fd_is_valid(int fd) 
{ 
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF; 
} 
+3

'F_GETFD' सिद्धांत में सस्ता है क्योंकि यह केवल कर्नेल स्पेस में (प्रक्रिया-स्थानीय) फ़ाइल डिस्क्रिप्टर को संदर्भित करता है, न कि अंतर्निहित खुली फ़ाइल विवरण (प्रक्रिया-साझा) जो इसका संदर्भ देता है। –

+0

@ आर .. जानकारी के लिए धन्यवाद, तय। –

+1

'fcntl' को कॉल करने से पहले आपको 'errno' शून्य पर सेट करना चाहिए। आपके फ़ंक्शन को कॉल करने से पहले 'errno' 'EBADF' के बराबर हो सकता है और' fcntl' केवल त्रुटि के मामले में इसे बदल देगा। – Bilow

3

मुझे नहीं लगता कि कोई ऐसा फ़ंक्शन है जो आपको बता सकता है कि वर्णनकर्ता अभी भी मान्य है या नहीं। वर्णनकर्ता आमतौर पर 6 की तरह एक छोटा पूर्णांक होता है और यदि आप फ़ाइल बंद करते हैं और बाद में एक नया खोलते हैं तो आपका libc उस नंबर का पुन: उपयोग करना चुन सकता है।

इसके बजाय, आपको फ़ाइल वर्णनकर्ता की प्रतिलिपि बनाने के लिए dup() का उपयोग करने पर विचार करना चाहिए। एकाधिक स्थानों में एक ही वर्णनकर्ता का उपयोग करने के बजाय फ़ाइल डिस्क्रिप्टर को डुप्लिकेट करके, यह जानना आपके लिए आसान हो सकता है कि फाइल डिस्क्रिप्टर अभी भी वैध है या नहीं। जब आप पूरा कर लेंगे तो आपको केवल मूल वर्णनकर्ता और डुप्लिकेट दोनों को बंद करना होगा।

+0

गलत। से मेरा और आर .. का जवाब। –

+3

डेविड "सही" है जिसमें आप यह निर्धारित नहीं कर सकते कि क्या वर्णनकर्ता "* अभी भी वैध है"। आप बता सकते हैं कि यह मान्य है, लेकिन यह आपको इस बारे में कोई जानकारी नहीं देता है कि यह अभी भी एक ही संसाधन को संदर्भित करता है या नहीं। –

+1

हां। वैध की मेरी परिभाषा यह है कि यह अभी भी उसी चीज को इंगित करता है जिसका उपयोग किया जाता था। मुझे लगता है कि यह एक अच्छी परिभाषा है क्योंकि यह आमतौर पर आप जो चाहते हैं और आप बता सकते हैं कि क्या वर्णनकर्ता अभी भी कोड को देखकर वैध है या नहीं; यह अपरिभाषित व्यवहार पर निर्भर नहीं है। –

3

this मंच लेख से:

int is_valid_fd(int fd) 
{ 
    return fcntl(fd, F_GETFL) != -1 || errno != EBADF; 
} 

fcntl (GETFL) शायद सबसे सस्ता और कम से कम आपरेशन आप एक फ़ाइल वर्णनकर्ता पर प्रदर्शन कर सकते हैं असफल होने की संभावना। विशेष रूप से, विनिर्देश बताता है कि इसे सिग्नल द्वारा बाधित नहीं किया जा सकता है, न ही यह किसी भी प्रकार के लॉक से कहीं भी प्रभावित होता है।

+3

आपके स्रोतों को श्रेय देने के बारे में: http://cboard.cprogramming.com/networking-device-communication/93683-checking-if-file-descriptor-valid.html#post678998 – Kev

0

मुझे ऐसा लगता है कि अगर आप यदि यह अभी भी एक ही संसाधन के लिए अंक जानना चाहता हूँ, एक (गैर सही) दृष्टिकोण fstat() वर्णनकर्ता बस खुला और फिर बाद में के बाद आप इसे फिर से कर सकते हैं और हो सकता है परिणामों की तुलना करें। .st_mode & S_IFMT देखकर शुरू करें और वहां से जाएं - क्या यह एक फाइल सिस्टम ऑब्जेक्ट है? .st_dev/.st_ino. पर एक सॉकेट है? getsockname(), getpeername() आज़माएं। यह 100% निश्चित नहीं होगा, लेकिन यह आपको बता सकता है कि यह निश्चित रूप से वही नहीं है।

-1

मैंने इस समस्या को हल किया। मुझे नहीं पता कि इसका सामान्य उद्देश्य के लिए उपयोग किया जा सकता है लेकिन सीरियल कनेक्शन के लिए यह ठीक काम करता है (उदा।/dev/ttyUSB0)!

struct stat s; 
fstat(m_fileDescriptor, &s); 

// struct stat::nlink_t st_nlink; ... number of hard links 
if(s.st_nlink < 1){ 
// treat device disconnected case 
} 

विवरण के लिए उदा। आदमी पेज http://linux.die.net/man/2/fstat

चीयर्स, फ़्लो