हालांकि स्टैक ओवरफ्लो प्रश्न पहले ही पर्याप्त लग रहा था, मैं समझता हूं, आपकी टिप्पणियों से, आपको अभी भी इस बारे में संदेह क्यों हो सकता है। मेरे लिए, यह दो UNIX उपप्रणालियों (प्रक्रियाओं और फाइलों) को संप्रेषित करने पर ठीक उसी प्रकार की महत्वपूर्ण स्थिति है, जिसमें शामिल है।
जैसा कि आप जानते हैं, UNIX सिस्टम आमतौर पर दो सबसिस्टम में विभाजित होते हैं: फाइल सबसिस्टम, और प्रोसेस सबसिस्टम। अब, जब तक कि इसे निर्देश नहीं दिया जाता है अन्यथा एक सिस्टम कॉल के माध्यम से, कर्नेल में ये दोनों उपतंत्र एक दूसरे के साथ बातचीत नहीं करनी चाहिए। हालांकि एक अपवाद है: एक निष्पादन योग्य फ़ाइल को एक प्रक्रिया के पाठ क्षेत्रों में लोड करना । बेशक, कोई यह तर्क दे सकता है कि इस ऑपरेशन को सिस्टम कॉल ( execve
) द्वारा भी ट्रिगर किया गया है , लेकिन यह आमतौर पर एक मामले के लिए जाना जाता है जहां प्रक्रिया सबसिस्टम फ़ाइल सबसिस्टम के लिए एक अंतर्निहित अनुरोध करता है।
क्योंकि प्रक्रिया सबसिस्टम में स्वाभाविक रूप से फ़ाइलों को संभालने का कोई तरीका नहीं है (अन्यथा पूरी चीज़ को दो में विभाजित करने का कोई मतलब नहीं होगा), इसमें फ़ाइलों का उपयोग करने के लिए फ़ाइल सबसिस्टम को प्रदान करने के लिए जो भी उपयोग करना होगा। इसका अर्थ यह भी है कि फ़ाइल उप संस्करण / विलोपन के बारे में फ़ाइल सबसिस्टम को मापने के लिए जो कुछ भी उपाय किया जाता है वह सब-सिस्टम सबमिशन प्रस्तुत करता है। इस बिंदु पर, मैं इस U & L प्रश्न के बारे में गिल्स के उत्तर को पढ़ने की सलाह दूंगा । मेरा बाकी का जवाब गिल्स के इस सामान्य से अधिक पर आधारित है।
पहली बात यह है कि ध्यान दिया जाना चाहिए कि आंतरिक रूप से, फ़ाइलें केवल इनोड के माध्यम से सुलभ हैं । यदि कर्नेल को एक रास्ता दिया जाता है, तो इसका पहला कदम अन्य सभी कार्यों के लिए उपयोग किए जाने वाले इनोड में अनुवाद करना होगा। जब कोई प्रक्रिया किसी निष्पादन योग्य को मेमोरी में लोड करती है, तो वह इसे अपने इनोड के माध्यम से करता है, जो एक पथ के अनुवाद के बाद फ़ाइल सबसिस्टम द्वारा प्रदान किया गया है। आईनोड कई रास्तों (लिंक) से जुड़ा हो सकता है, और प्रोग्राम केवल लिंक को हटा सकते हैं। किसी फ़ाइल और इनोड को हटाने के लिए, उपयोगकर्ता को उस इनोड के सभी मौजूदा लिंक को हटाना होगा, और यह सुनिश्चित करना होगा कि यह पूरी तरह से अप्रयुक्त है। जब ये स्थितियां पूरी हो जाती हैं, तो कर्नेल स्वचालित रूप से डिस्क से फ़ाइल को हटा देगा।
यदि आपके पास गिल्स के उत्तर के निष्पादन योग्य भाग की जगह पर एक नज़र है , तो आप देखेंगे कि आप फ़ाइल को कैसे संपादित / हटाते हैं, इसके आधार पर कर्नेल अलग-अलग तरीके से प्रतिक्रिया / अनुकूलन करेगा, जो हमेशा फ़ाइल सबसिस्टम के भीतर कार्यान्वित तंत्र के माध्यम से होता है।
- यदि आप एक रणनीति बनाते हैं ( शून्य / लिखना / खोलना / लिखना या खोलना / लिखना / नए आकार में छोटा करना ), तो आप देखेंगे कि कर्नेल आपके अनुरोध को संभालने में परेशान नहीं करेगा। आपको एक त्रुटि 26 मिलेगी: पाठ फ़ाइल व्यस्त (
ETXTBSY
)। चाहे कोई भी परिणाम हो।
- यदि आप दो रणनीति की कोशिश करते हैं, तो पहला कदम आपके निष्पादन योग्य को हटाना है। हालाँकि, चूंकि यह एक प्रक्रिया द्वारा उपयोग किया जा रहा है, फ़ाइल सबसिस्टम डिस्क में से फ़ाइल को (और इसके इनसाइड) को सही मायने में डिलीट करने से रोक देगा । इस बिंदु से, पुरानी फ़ाइल की सामग्री तक पहुंचने का एकमात्र तरीका यह है कि इसे अपने इनोड के माध्यम से किया जाए, यही प्रक्रिया सबसिस्टम तब करता है जब उसे नए डेटा को पाठ अनुभागों में लोड करने की आवश्यकता होती है (आंतरिक रूप से, रास्तों का उपयोग करने का कोई मतलब नहीं है, सिवाय जब उन्हें इनोड में अनुवाद करते हुए)। भले ही आपने अनलिंक किया होफ़ाइल (उसके सभी पथ हटा दिए गए), प्रक्रिया अभी भी इसका उपयोग कर सकती है जैसे कि आपने कुछ नहीं किया। पुराने पथ के साथ एक नई फ़ाइल बनाने से कुछ भी नहीं बदलता है: नई फ़ाइल को पूरी तरह से नया इनकोड दिया जाएगा, जिसके चलने की प्रक्रिया का कोई ज्ञान नहीं है।
रणनीतियाँ 2 और 3 निष्पादनयोग्य के लिए भी सुरक्षित हैं: यद्यपि निष्पादन योग्य (और गतिशील रूप से भरी हुई लाइब्रेरी) फ़ाइल डिस्क्रिप्टर होने के अर्थ में फाइलें नहीं खुली हैं, वे बहुत ही समान तरीके से व्यवहार करते हैं। जब तक कोई प्रोग्राम कोड चला रहा होता है, तब तक फ़ाइल बिना डिस्क प्रविष्टि के भी डिस्क पर रहती है।
- रणनीति तीन काफी समान है क्योंकि
mv
ऑपरेशन एक परमाणु है। यह संभवतः rename
सिस्टम कॉल के उपयोग की आवश्यकता होगी , और चूंकि कर्नेल मोड में प्रक्रियाओं को बाधित नहीं किया जा सकता है, इस ऑपरेशन के पूरा होने तक कुछ भी हस्तक्षेप नहीं कर सकता (सफलतापूर्वक या नहीं)। फिर से, पुरानी फ़ाइल के इनकोड में कोई परिवर्तन नहीं होता है: एक नया बनाया जाता है, और पहले से चल रही प्रक्रियाओं को इसका कोई ज्ञान नहीं होगा, भले ही यह पुराने इनोड के लिंक में से एक के साथ जुड़ा हो।
रणनीति 3 के साथ, नई फ़ाइल को मौजूदा नाम पर ले जाने का चरण पुरानी सामग्री के लिए निर्देशिका प्रविष्टि को हटाता है और नई सामग्री के लिए निर्देशिका प्रविष्टि बनाता है। यह एक परमाणु संचालन में किया जाता है, इसलिए इस रणनीति का एक बड़ा फायदा होता है: यदि किसी भी समय फ़ाइल एक प्रक्रिया को खोलती है, तो यह या तो पुरानी सामग्री या नई सामग्री को देखेगा - मिश्रित सामग्री या फ़ाइल नहीं होने का कोई जोखिम नहीं है मौजूदा।
किसी फ़ाइल को पुनःप्रमाणित करना : जब उपयोग करना gcc
(और व्यवहार संभवतः कई अन्य संकलक के लिए समान है), आप रणनीति 2 का उपयोग कर रहे हैं। आप देख सकते हैं कि strace
आपके कंपाइलर की प्रक्रियाओं को चलाकर :
stat("a.out", {st_mode=S_IFREG|0750, st_size=8511, ...}) = 0
unlink("a.out") = 0
open("a.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
chmod("a.out", 0750) = 0
- कंपाइलर पता लगाता है कि फ़ाइल पहले से मौजूद है
stat
और lstat
सिस्टम कॉल के माध्यम से ।
- फाइल अनलिंक है । यहां, जबकि यह अब नाम के माध्यम से सुलभ नहीं है
a.out
, इसकी इनोड और सामग्री डिस्क पर बनी हुई है, जब तक कि वे पहले से चल रही प्रक्रियाओं द्वारा उपयोग किए जा रहे हैं।
- नाम के तहत एक नई फ़ाइल बनाई और निष्पादित की जाती है
a.out
। यह एक बिलकुल नया आईनोड है, और एकदम नई सामग्री, जो पहले से चल रही प्रक्रियाओं की परवाह नहीं करती है।
अब, जब साझा लाइब्रेरी की बात आती है, तो वही व्यवहार लागू होगा। जब तक एक लाइब्रेरी ऑब्जेक्ट का उपयोग एक प्रक्रिया द्वारा किया जाता है, तब तक इसे डिस्क से हटाया नहीं जाएगा, भले ही आप इसके लिंक को कैसे बदलें। जब भी किसी चीज़ को मेमोरी में लोड करना होता है, तो कर्नेल इसे फाइल के इनकोड के माध्यम से करेगा, और इसलिए आप इसके लिंक में किए गए परिवर्तनों को अनदेखा करेंगे (जैसे कि उन्हें नई फ़ाइलों के साथ जोड़ना)।