2009-03-29 8 views
5

यदि मैं लिखने के लिए अपने लिखने() सिस्टम कॉल पर गिन रहा हूं, उदाहरण के लिए, 100 बाइट्स, मैं हमेशा उस लूप में कॉल लिखता हूं() कॉल करता है जो यह देखने के लिए जांच करता है कि लौटाई गई लंबाई क्या है जो मुझे भेजने की उम्मीद है और, यदि नहीं, तो यह बफर सूचक को टक्कर देता है और लिखी गई राशि से लंबाई कम करता है।लिखने() सिस्टम कॉल कब अनुरोध किया गया बफर बनाम सभी आंशिक लेखन कर रहा है?

तो एक बार फिर मैंने यह किया, लेकिन अब स्टैक ओवरफ्लो है, मैं लोगों से यह पूछ सकता हूं कि जब मेरे लोग लिखेंगे तो मेरे लिखने के बाद मैं उन सभी को लिखूंगा जो मुझे बनाम आंशिक लेखन वापस देते हैं?

अतिरिक्त टिप्पणियां: एक्स-इस्टेंस के जवाब ने मुझे याद दिलाया कि मुझे यह ध्यान रखना चाहिए था कि फाइल डिस्क्रिप्टर अवरुद्ध कर रहा था (यानी, गैर-अवरुद्ध नहीं)। मुझे लगता है कि वह सुझाव दे रहे हैं कि अवरुद्ध फ़ाइल डिस्क्रिप्टर पर एक लिखने का एकमात्र तरीका सभी निर्दिष्ट डेटा नहीं लिखेंगे जब लिखने() को सिग्नल द्वारा बाधित किया जाता है। ऐसा लगता है कि मुझे कम से कम सहज ज्ञान हो रहा है ...

उत्तर

3

आपको यह देखने के लिए इरनो की जांच करनी है कि क्या आपका कॉल बाधित हो गया है, या क्यों लिखना() जल्दी लौटाया गया है, और क्यों उसने केवल बाइट्स की एक निश्चित संख्या लिखी है।

ऐसे सॉकेट कि अधीन हैं प्रवाह नियंत्रण के लिए, लिखने() और writev() का अनुरोध किया की तुलना में कम बाइट्स लिख सकते हैं के रूप में man 2 write

से

वस्तुओं पर गैर अवरुद्ध I/O का उपयोग करते समय; वापसी मूल्य ध्यान दिया जाना चाहिए, और जब भी संभव हो ऑपरेशन के शेष को फिर से प्रयास किया जाना चाहिए।

असल में, जब तक कि आप एक गैर-अवरुद्ध सॉकेट पर लिख रहे हों, तब तक ऐसा ही होगा जब आप सिग्नल द्वारा बाधित हो जाते हैं।

[EINTR] एक सिग्नल इसे पूरा होने से पहले लिखने में बाधा डालता है।

man page में त्रुटियों के अनुभाग को वापस लौटाया जा सकता है, और जब इसे वापस किया जाएगा, तो अधिक जानकारी के लिए त्रुटियों अनुभाग देखें। वहां से आपको यह पता लगाने की आवश्यकता है कि क्या त्रुटि किसी त्रुटि को लॉग करने और छोड़ने के लिए पर्याप्त गंभीर है, या यदि आप ऑपरेशन जारी रख सकते हैं!

इस पुस्तक में सभी चर्चा की गई है: Advanced Unix Programming by Marc J. Rochkind, मैंने इस पुस्तक की सहायता से अनगिनत कार्यक्रम लिखे हैं, और ओएस जैसे ओएनएक्स के लिए प्रोग्रामिंग करते समय इसका सुझाव देंगे।

+0

स्पष्ट होने के लिए, लिनक्स पर, 'errno' _not_ सेट है जब लिखने से कुछ गैर-शून्य संख्या बाइट्स लिखते हैं, भले ही अनुरोधित राशि से कम हो। यह _only_ सेट है जब 0 बाइट्स लिखे जाते हैं। तो आम तौर पर आप यह नहीं समझ सकते कि क्यों लिखना _partial_ था, लेकिन यदि स्थिति लगातार है (उदाहरण के लिए, डिस्क भर चुकी है) तो आप ** अगले ** लिखने पर पाएंगे, जो वापसी मूल्य के साथ विफल हो जाएगा '- 1' और 'errno' सेट करें। यहां एक [क्लासिक थ्रेड] (http://yarchive.net/comp/linux/partial_reads_writes.html) है, ऐसा क्यों है। – BeeOnRope

-1

लिखने के पास कभी भी आंशिक बफर afaik लिखने का कोई कारण नहीं होना चाहिए। आंशिक लेखन के बारे में सोचने के संभावित कारण यह है कि यदि आप डिस्क स्थान से बाहर हैं, तो आप ब्लॉक डिवाइस के अंत में लिख रहे हैं, या यदि आप किसी चार डिवाइस/किसी अन्य प्रकार के डिवाइस पर लिख रहे हैं।

हालांकि, पुन: प्रयास करने की योजना अंधेरे से लिखती है शायद यह एक अच्छा नहीं है - यह देखने के लिए गलत जांचें कि आपको पहले पुनः प्रयास करना चाहिए या नहीं।

+0

आप त्रुटि पर भरोसा नहीं कर सकते क्योंकि यह कोई त्रुटि नहीं है, Artyom उत्तर जाने का तरीका है। सामान्य मामले के लिए सलाह देना गलत है, चार डिवाइस, फीफो, सॉकेट इत्यादि ... वैसे भी असामान्य नहीं हैं, और आप नहीं जानते कि कोड कहां या कब उपयोग किया जाएगा। – shodanex

+0

यह वही है जो मैंने कहा - यह देखने के लिए इरनो को जांचें कि आपको –

+0

फिर से प्रयास करना चाहिए, लेकिन आंशिक लेखन कोई त्रुटि नहीं है इसलिए – shodanex

5

लिखना आंशिक लेखन वापस कर सकता है विशेष रूप से सॉकेट पर संचालन या आंतरिक बफर भरने पर। तो अच्छा तरीका निम्न करने के लिए है:

while(size > 0 && (res=write(fd,buff,size))!=size) { 
    if(res<0 && errno==EINTR) 
     continue; 
    if(res < 0) { 
     // real error processing 
     break; 
    } 
    size-=res; 
    buf+=res; 
} 

कभी क्या आमतौर पर होता है पर रिले ...

ध्यान दें: पूर्ण डिस्क के मामले में आप ENOSPC नहीं आंशिक लिखने मिलेगा।

+1

जांचने के लिए कुछ भी नहीं है आपका कोड भाग में पढ़ता है: 'size = -res;'। ऐसा नहीं होना चाहिए: 'आकार- = res;'? – Urhixidur

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