2009-01-22 11 views
18

Win32 का CreateFileFILE_FLAG_DELETE_ON_CLOSE है, लेकिन मैं लिनक्स पर हूं।प्रोग्राम समाप्ति (सी/सी ++) पर गारंटीकृत फ़ाइल हटाना

मैं एक अस्थायी फ़ाइल खोलना चाहता हूं जो हमेशा प्रोग्राम समाप्ति पर हटा दी जाएगी। मैं समझ सकता हूं कि प्रोग्राम क्रैश के मामले में यह गारंटी देने के लिए व्यावहारिक नहीं हो सकता है, लेकिन किसी भी अन्य मामले में मैं इसे काम करना चाहता हूं।

मुझे राय के बारे में पता है। मुझे सिग्नल के बारे में पता है। मुझे atexit(3) के बारे में पता है। मुझे पता है कि मैं फ़ाइल खोल सकता हूं और इसे तुरंत हटा सकता हूं और फ़ाइल तब तक पहुंच योग्य रहेगी जब तक फाइल डिस्क्रिप्टर बंद नहीं होता है (जो एक दुर्घटना भी संभालता है)। इनमें से कोई भी एक पूर्ण और स्पष्ट समाधान की तरह लग:

  1. आरए II: वहाँ गया, किया है कि: मैं एक वस्तु जिसका नाशक फ़ाइल को हटा देता है, लेकिन यदि प्रोग्राम एक संकेत से समाप्त हो जाता है नाशक नहीं बुलाया जाता है।
  2. सिग्नल: मैं एक निम्न स्तरीय लाइब्रेरी लिख रहा हूं जो सिग्नल हैंडलर को एक मुश्किल प्रस्ताव पंजीकृत कर देता है। उदाहरण के लिए, यदि एप्लिकेशन सिग्नल का उपयोग करता है तो क्या होगा? मैं किसी भी पैर की उंगलियों पर कदम नहीं उठाना चाहता। मैं सामना करने के लिए sigaction(2) के कुछ चालाक उपयोग पर विचार कर सकता हूं ... लेकिन इस संभावना में अभी तक पर्याप्त विचार नहीं किया है।
  3. atexit(3): स्पष्ट रूप से बेकार, क्योंकि इसे असामान्य समाप्ति के दौरान नहीं कहा जाता है (उदाहरण के लिए सिग्नल के माध्यम से)।
  4. प्रीemptive unlink(2): यह बहुत अच्छा है सिवाय इसके कि मुझे फाइल सिस्टम में दिखाई देने के लिए फ़ाइल की आवश्यकता है (अन्यथा सिस्टम मॉनिटर/समस्या निवारण के लिए कठिन है)।

आप यहां क्या करेंगे?

अधिक विवरण

मैं अपने मूल पोस्ट मैं अब जो एहसास मैं शामिल हो जाना चाहिए था में एक विस्तार elided। इस मामले में "फ़ाइल" सख्ती से एक सामान्य फ़ाइल नहीं है, बल्कि एक POSIX संदेश कतार है। मैं इसे mq_open() के माध्यम से बना देता हूं। इसे mq_close() या close() (पूर्व में मेरे सिस्टम पर उत्तरार्द्ध के लिए उपनाम है) के माध्यम से बंद किया जा सकता है। इसे mq_unlink() के माध्यम से सिस्टम से हटाया जा सकता है। यह सब एक नियमित फ़ाइल, के समान को छोड़कर बनाता है कि मैं उस निर्देशिका को नहीं चुन सकता जिसमें फ़ाइल रहता है। यह वर्तमान सबसे लोकप्रिय उत्तर बनाता है (फ़ाइल को /tmp में रखकर) अनावश्यक है, क्योंकि प्रणाली द्वारा "फ़ाइल" को वर्चुअल फाइल सिस्टम में बहुत सीमित क्षमता वाले सिस्टम द्वारा बनाया गया है। (मैंने में वर्चुअल फाइल सिस्टम को man mq_overview में उदाहरण के बाद आरोहित किया है)।

यह भी बताता है कि मुझे दिखाई देने के लिए नाम क्यों चाहिए (तत्काल-अनलिंक दृष्टिकोण को अनावश्यक बनाने के लिए): "फ़ाइल" को दो या दो से अधिक प्रक्रियाओं के बीच साझा किया जाना चाहिए।

+0

यह आइटम 4 है (नाम सुलभ रखने के लिए) जो इसे कठिन बनाता है। –

+0

हर बार एक महत्वपूर्ण जानकारी छोड़ दी जाती है, जवाब घबराते हैं। आप अगली बार के लिए पता चल जाएगा। –

उत्तर

7

प्रक्रिया चल रही है, जबकि नाम चल रहा है, यह आवश्यक है कि यह हासिल करना मुश्किल हो। क्या आप उस आवश्यकता पर फिर से जा सकते हैं?

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

ध्यान दें कि सिग्नल हैंडलिंग एक अपूर्ण रणनीति है; सिगकिल पकड़ा नहीं जा सकता है, और अतुलनीय() हैंडलर नहीं कहा जाएगा, और फ़ाइल को छोड़ दिया जाएगा।

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

+1

मुझे विश्वास नहीं है कि मैं फ़ाइल नाम दृश्यता के लिए आवश्यकता को हटा सकता हूं। मैंने मूल प्रश्न में "आगे स्पष्टीकरण" जोड़ा जो बताता है कि यह एक नियमित फ़ाइल नहीं है, और यह बहुत सीमित क्षमता वाले एक निश्चित स्थान पर रहता है। मुझे लगता है कि मुझे निगरानी के लिए फाइलें दिखने की ज़रूरत है। –

+0

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

+0

ओह, और मुझे मत भूलना, नाम सामान्य ऑपरेशन के दौरान दृश्यमान रहने की आवश्यकता है क्योंकि उन्हें प्रोग्राम के बीच साझा किया जाता है। मैं उनकी रचना के तुरंत बाद उन्हें अनलिंक नहीं कर सकता - जो उन्हें बेकार प्रदान करेगा। मुझे मूल रूप से इसके बारे में स्पष्ट होना चाहिए था। –

6

यदि आप केवल एक अस्थायी फ़ाइल बना रहे हैं, तो इसे /tmp या इसके उपनिर्देशिका में बनाएं। फिर atexit(3) या इसी तरह के दौरान किए जाने पर इसे हटाने का सबसे अच्छा प्रयास करें। जब तक आप mkstemp(3) के माध्यम से चुने गए अद्वितीय नामों का उपयोग करते हैं या एक प्रोग्राम क्रैश के कारण इसे हटाए जाने में भी असफल होते हैं, तो आप इसे बाद के रनों या अन्य ऐसी स्थितियों पर फिर से पढ़ने का जोखिम नहीं उठाते हैं।

उस बिंदु पर यह /tmp को साफ रखने की प्रणाली-स्तर की समस्या है। अधिकांश डिस्ट्रोज़ इसे बूट या शटडाउन पर मिटा देते हैं, या पुराने फाइलों को हटाने के लिए नियमित cronjob चलाते हैं।

+0

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

3

अतीत में, मैंने एक "अस्थायी फ़ाइल प्रबंधक" बनाया है जो अस्थायी फ़ाइलों का ट्रैक रखता है।

कोई प्रबंधक से अस्थायी फ़ाइल नाम का अनुरोध करेगा और यह नाम पंजीकृत था।

एक बार आपको अस्थायी फ़ाइल नाम की आवश्यकता नहीं होने के बाद, आप प्रबंधक को सूचित करते हैं और फ़ाइल नाम अनियंत्रित है।

एक समाप्ति संकेत प्राप्त होने पर, सभी पंजीकृत अस्थायी फ़ाइलों को नष्ट कर दिया गया।

अस्थायी फ़ाइल नाम टकराव से बचने के लिए यूयूआईडी थे।

+0

जटिल, लेकिन स्पष्ट रूप से यह काम करता है - दोगुना इसलिए अगर अस्थायी फ़ाइल प्रबंधक का पता लगाने का कोई तरीका है कि अस्थायी फ़ाइल का अनुरोध करने वाली प्रक्रिया अभी भी मौजूद है या नहीं। अगर उस प्रक्रिया कांटेदार थोड़ा मुश्किल हो जाता है; दोगुना तो अगर माता-पिता निकलते हैं। –

+0

आप एक आवश्यकता जोड़ सकते हैं कि जब एक प्रक्रिया कांटा, माता-पिता को बच्चे की प्रक्रिया के पिड के प्रबंधक को सूचित करना होगा। यह अन्य प्रकार की इंटर-प्रोसेस कॉम की लचीलापन भी देता है। टीएमपी फ़ाइल के फ़ाइल नाम को पास करने के लिए इस्तेमाल किया जाना है। – KeithB

+0

डेविड, आपका उत्तर लगता है जैसे यह "प्रबंधक" एक ही प्रक्रिया में मॉड्यूल के रूप में रहता है। जोनाथन की टिप्पणी यह ​​ध्वनि बनाती है जैसे यह एक अलग प्रक्रिया होगी। मैं देख सकता हूं कि यह एक अलग प्रक्रिया के रूप में कैसे काम कर सकता है, निश्चित रूप से, लेकिन क्या आप सुझाव दे रहे थे कि यह प्रक्रिया में हो सकता है? यदि ऐसा है तो मुझे उतना मूल्य नहीं दिखता है .... –

0

फ़ाइल बनाने के बाद आपके पास प्रक्रिया कांटा हो सकता है, और उसके बाद बच्चे को बंद करने की प्रतीक्षा करें, और फिर अभिभावक फ़ाइल को अनलिंक कर सकता है और बाहर निकल सकता है।

4

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

यदि आपकी मूल प्रक्रिया भी मर जाती है, तो आप भाग्य से काफी अधिक हैं, लेकिन अधिकांश स्क्रिप्ट वातावरण काफी मजबूत हैं और शायद ही कभी मर जाते हैं जब तक कि स्क्रिप्ट टूटा न जाए, जो प्रोग्राम से सही रखना अक्सर आसान होता है।

+1

असल में, यह एक बहुत अच्छा विचार है - सिवाय इसके कि यह एक निम्न स्तर की लाइब्रेरी है जिसे लिखा जा रहा है। लाइब्रेरी प्रारंभिक दिनचर्या फ़ाइल और फिर कांटा बनाते हैं। बच्चा सभी असली काम करने जा रहा है। माता-पिता बस वहां बैठते हैं, बच्चे को समाप्त करने की प्रतीक्षा करते हैं, फिर फ़ाइल को हटा देते हैं। –

+1

दिनचर्या के एक सामान्य उद्देश्य सेट में औचित्य साबित करना मुश्किल है; कार्यक्रम की प्रक्रिया संरचना पर अपनी आवश्यकताओं हो सकती है। यदि यह अनुमत है - आपके पास ग्राहकों का पर्याप्त नियंत्रण है - तो यह बहुत प्रभावी होगा। –

1

मैं सिर्फ stackoverflow शामिल हो गए और आप यहां पाया :)

आप कर रहे हैं समस्या MQ फाइलों का प्रबंधन और उन्हें ढेर से रखने के लिए है, तो आप वास्तव में समाप्ति पर फ़ाइल हटाने की गारंटी करने के लिए जरूरत नहीं है। अगर आप जर्नल रखने से बेकार फाइलें चाहते हैं, तो आपको जर्नल रखने की आवश्यकता हो सकती है। एक एमक खोले जाने के बाद जर्नल फ़ाइल में एक एंट्री जोड़ें, जब इसे बंद किया जाता है तो दूसरी प्रविष्टि, और जब आपकी लाइब्रेरी शुरू होती है, तो पत्रिका में असंगतता की जांच करें और असंगतता को सही करने के लिए आवश्यक कार्रवाई करें। यदि आप mq_open/mq_close कह रहे हैं तो क्रैश होने की चिंता करते हैं, तो आप उन कार्यों को कॉल करने से ठीक पहले एक जर्नल एंट्री भी जोड़ सकते हैं।

0

क्या आप वास्तव में नाम दिखने के लिए नाम की आवश्यकता है?

मान लीजिए कि आप फ़ाइल को तुरंत अनलिंक करने का विकल्प लेते हैं। तब:

  • रिक्तिपूर्व अनलिंक (2): इस (अन्यथा प्रणाली कठिन है पर नजर रखने के/निवारण) सिवाय इसके कि मैं फ़ाइल की आवश्यकता फाइल सिस्टम पर मौजूद रहे करने के लिए बहुत अच्छा है।

    आप अभी भी हटाए गए फ़ाइल पर डीबग कर सकते हैं, क्योंकि यह अभी भी /proc/$pid/fd/ के अंतर्गत दिखाई देगा। जब तक आप अपनी प्रक्रियाओं की बोलियों को जानते हैं, तब तक उनकी खुली फाइलों का आकलन करना आसान होना चाहिए।

  • नाम सामान्य ऑपरेशन के दौरान दृश्यमान रहने की आवश्यकता है क्योंकि उन्हें प्रोग्राम के बीच साझा किया जाता है।

    आप यूनिक्स डोमेन सॉकेट पर फ़ाइल डिस्क्रिप्टर के चारों ओर गुजरकर प्रक्रियाओं के बीच हटाई गई खुली फ़ाइल साझा कर सकते हैं। अधिक जानकारी के लिए Portable way to pass file descriptor between different processes देखें।

0
  • अपने डॉट निर्देशिका के अंतर्गत अस्थायी फ़ाइलों के लिए एक किताब रखने निर्देशिका है।
  • एक temp-file बनाते समय, पहले पुस्तक-रखरखाव फ़ाइल को पुस्तक-रखरखाव निर्देशिका में बनाएं जिसमें पथ या यूआईआईडी आपके अस्थायी फ़ाइल में हो।
  • उस temp फ़ाइल को बनाएँ।
  • जब temp-file हटा दी जाती है, तो पुस्तक-रखरखाव फ़ाइल हटाएं।
  • जब प्रोग्राम शुरू होता है, तो अस्थायी फ़ाइलों के पथ वाले किसी भी फाइल के लिए पुस्तक-रखरखाव निर्देशिका को स्कैन करें और यदि उन्हें मिला तो उन्हें हटाने का प्रयास करें, वे पुस्तक-रखरखाव फ़ाइलों को हटा दें।
  • (noisily लॉग इन करता है, तो किसी भी कदम विफल रहता है।)

मैं तरीके यह किसी भी तरह सरल करने के लिए नहीं दिख रहा। यह बॉयलरप्लेट है जो किसी भी उत्पादन गुणवत्ता कार्यक्रम के माध्यम से जाना चाहिए; आसानी से +500 लाइनें।

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