2011-01-16 14 views
13

टिम ब्रै के लेख "Saving Data Safely" में खुले प्रश्नों के साथ मुझे छोड़ दिया गया ext4/fsync स्थिति अस्पष्ट है। आज, यह एक महीने से अधिक पुराना है और मैंने इस पर कोई फॉलो-अप नहीं देखा है, इसलिए मैंने यहां विषय को संबोधित करने का फैसला किया।एंड्रॉइड (जावा)

लेख का एक बिंदु यह है कि FileOutputStream का उपयोग करते समय FileDescriptor.sync() को सुरक्षित पक्ष पर कॉल किया जाना चाहिए। सबसे पहले, मैं बहुत चिंतित था, क्योंकि मैंने जावा के 12 साल के दौरान कोई भी जावा कोड सिंक नहीं किया है। खासकर फाइलों के साथ मुकाबला करने के बाद एक सुंदर मूल बात है। साथ ही, FileOutputStream के मानक JavaDoc को समन्वयित करने पर संकेत नहीं दिया गया (जावा 1.0 - 6)। कुछ शोध के बाद, मुझे लगा कि ext4 वास्तव में पहली मुख्यधारा फ़ाइल प्रणाली हो सकती है जो समन्वयन की आवश्यकता है। (वहाँ अन्य फ़ाइल सिस्टम जहां स्पष्ट सिंक्रनाइज़ सलाह दी जाती है क्या?)

मैं इस मामले पर कुछ सामान्य विचार की सराहना करते हैं, लेकिन मैं भी कुछ विशिष्ट प्रश्न हैं:

  1. जब एंड्रॉयड फाइल सिस्टम के लिए सिंक करना होगा ? यह आवधिक और अतिरिक्त रूप से जीवन चक्र घटनाओं के आधार पर हो सकता है (उदाहरण के लिए एक ऐप की प्रक्रिया पृष्ठभूमि में जाती है)।
  2. क्या FileDescriptor.sync() मेटा डेटा को सिंक करने का ख्याल रखता है? वह बदली गई फाइल की निर्देशिका को सिंक कर रहा है। FileChannel.force() से तुलना करें।
  3. आमतौर पर, कोई फ़ाइलऑटपुटस्ट्रीम में सीधे नहीं लिखता है। यहाँ मेरी समाधान है (आप सहमत हैं?):
     
    FileOutputStream fileOut = ctx.openFileOutput(file, Context.MODE_PRIVATE); 
    BufferedOutputStream out = new BufferedOutputStream(fileOut); 
    try { 
        out.write(something); 
        out.flush(); 
        fileOut.getFD().sync(); 
    } finally { 
        out.close(); 
    } 
    

उत्तर

10

जब यह जरूरत Android समन्वयन करना होगा - जैसे जब स्क्रीन बंद हो जाती हैं, तो डिवाइस, आदि को बंद करने पर आप सिर्फ देख रहे हैं के रूप में "सामान्य" ऑपरेशन, अनुप्रयोगों द्वारा स्पष्ट सिंक की आवश्यकता नहीं है।

समस्या तब होती है जब उपयोगकर्ता बैटरी को अपने डिवाइस से बाहर खींचता है (या कर्नेल का हार्ड रीसेट करता है), और आप यह सुनिश्चित करना चाहते हैं कि आप कोई डेटा न खोएं।

तो पहली बात यह समझने के लिए: मुद्दा तब होता है जब बिजली अचानक खो जाती है, इसलिए एक साफ शटडाउन नहीं हो सकता है, और उस बिंदु पर लगातार भंडारण में क्या होने वाला है।

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

यहां बड़ी चिंता तब होती है जब आप फ़ाइल को अपडेट करना चाहते हैं। उस मामले में, जब आप अगली फ़ाइल को पढ़ने आप या तोपिछले सामग्री, यानई सामग्री करना चाहते हैं। आप कुछ आधा रास्ता लिखे नहीं चाहते हैं, या डेटा खोना नहीं चाहते हैं।

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

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

+0

मुझे यह सुनिश्चित करने के लिए फ्लश() की उम्मीद होगी कि डिस्क पर सब कुछ लिखा गया है - अनिवार्य रूप से सिंक() को कॉल करके। क्या यह मामला नहीं है? –

+0

@a_horse_with_no_name: नहीं, यह नहीं है। _flush_ और _sync_ दो अलग-अलग ऑपरेशन हैं: फ्लश बस इंटरमीडिएट बफर फ्लश करता है; सिंक वास्तव में भंडारण के लिए लिखता है। उदाहरण देखें http://stackoverflow.com/questions/2340610/difference-between-fflush-and-fsync – sleske

+0

@sleske: स्पष्टीकरण के लिए धन्यवाद! –

1

fileOut.getFD().sync();close() से पहले, अंतिम खंड पर होना चाहिए।

sync() स्थायित्व पर विचार करते हुए close() से अधिक महत्वपूर्ण है।

तो, हर बार जब आप फ़ाइल पर काम करना 'खत्म' करना चाहते हैं तो आपको इसे close() से पहले करना चाहिए।

पॉज़िक्स गारंटी नहीं देता है कि जब आप close() जारी करते हैं तो लंबित लेखन डिस्क पर लिखे जाएंगे।

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