मुझे इसे तोड़ने दो।
जब आप एक निष्पादन योग्य चलाते हैं, तो सिस्टम कॉल का एक क्रम निष्पादित होता है, सबसे विशेष रूप से fork()
और execve()
:
fork()
कॉलिंग प्रक्रिया का एक बच्चा प्रक्रिया बनाता है, जो (ज्यादातर) माता-पिता की एक सटीक प्रतिलिपि है, दोनों अभी भी एक ही निष्पादन योग्य चल रहे हैं (कॉपी-ऑन-राइट मेमोरी पन्नों का उपयोग करके, इसलिए यह कुशल है)। यह दो बार लौटता है: माता-पिता में, यह बच्चे को पीआईडी लौटाता है। बच्चे में, यह 0. लौटता है। आम तौर पर, बच्चे की प्रक्रिया कॉल तुरंत निष्पादित होती है:
execve()
एक तर्क के रूप में निष्पादन योग्य के लिए एक पूरा रास्ता लेता है और निष्पादन योग्य के साथ कॉलिंग प्रक्रिया को बदल देता है। इस बिंदु पर नई बनाई गई प्रक्रिया को अपना खुद का वर्चुअल एड्रेस स्पेस यानी वर्चुअल मेमोरी मिल जाती है, और इसके एंट्री पॉइंट (प्लेटफॉर्म एबीआई द्वारा नए प्रोसेस के नियमों द्वारा निर्दिष्ट अवस्था में) पर निष्पादन शुरू हो जाता है।
इस बिंदु पर, कर्नेल के ईएलएफ लोडर ने निष्पादन योग्य के पाठ और डेटा खंडों को मेमोरी में मैप किया है, जैसे कि उसने mmap()
सिस्टम कॉल का उपयोग किया था (क्रमशः रीड-ओनली और प्राइवेट रीड-राइट मैपिंग के साथ)। BSS को मैप भी किया जाता है जैसे कि MAP_ANONYMOUS के साथ। (BTW, मैं यहाँ सादगी के लिए डायनेमिक लिंकिंग को नज़रअंदाज़ कर रहा हूँ: डायनामिक लिंकर open()
s और mmap()
s सभी डायनेमिक लाइब्रेरी मुख्य निष्पादन योग्य प्रविष्टि बिंदु पर कूदने से पहले।)
नव-निष्पादन () एड अपना कोड शुरू करने से पहले केवल कुछ पेज वास्तव में डिस्क से मेमोरी में लोड होते हैं। आगे के पन्नों की मांग है कि जरूरत पड़ने पर, अगर / जब प्रक्रिया अपने वर्चुअल एड्रेस स्पेस के उन हिस्सों को छू लेती है। (उपयोगकर्ता-स्पेस कोड निष्पादित करने के लिए शुरू करने से पहले कोड या डेटा के किसी भी पृष्ठ को प्री-लोड करना केवल एक प्रदर्शन अनुकूलन है।)
निष्पादन योग्य फ़ाइल को निचले स्तर पर इनोड द्वारा पहचाना जाता है। फ़ाइल को निष्पादित किया जाना शुरू होने के बाद, कर्नेल इनकोड संदर्भ द्वारा फ़ाइल सामग्री को अक्षुण्ण रखता है, फ़ाइल नाम से नहीं, जैसे कि ओपन फ़ाइल डिस्क्रिप्टर या फ़ाइल-समर्थित मेमोरी मैपिंग के लिए। तो आप आसानी से फाइल सिस्टम के किसी अन्य स्थान पर या एक अलग फाइल सिस्टम पर भी निष्पादन योग्य स्थानांतरित कर सकते हैं। साइड नोट के रूप में, प्रक्रिया के विभिन्न स्टेट को जांचने के लिए आप /proc/PID
(पीआईडी दी गई प्रक्रिया की प्रोसेस आईडी है) डायरेक्टरी में जा सकते हैं। आप निष्पादन योग्य फ़ाइल को भी खोल सकते हैं /proc/PID/exe
, यहां तक कि यह डिस्क से अनलिंक किया गया है।
अब चलते चलते खुदाई करते हैं:
जब आप किसी फ़ाइल को एक ही फाइल सिस्टम में स्थानांतरित करते हैं, तो सिस्टम कॉल जो निष्पादित होता है rename()
, जो फ़ाइल को किसी अन्य नाम में बदल देता है, फ़ाइल का इनोड वही रहता है।
जबकि दो अलग-अलग फाइल सिस्टम के बीच दो चीजें होती हैं:
फ़ाइल की सामग्री को पहले नए स्थान पर कॉपी करके, read()
औरwrite()
उसके बाद, फ़ाइल का उपयोग करके स्रोत निर्देशिका से अनलिंक किया जाता है unlink()
और स्पष्ट रूप से फ़ाइल को नए फाइल सिस्टम पर एक नया इनकोड मिलेगा।
rm
वास्तव में सिर्फ unlink()
डायरेक्टरी ट्री से दी गई फाइल है, इसलिए डायरेक्टरी पर लिखने की अनुमति होने से आपको उस डायरेक्टरी की किसी भी फाइल को हटाने का पर्याप्त अधिकार मिल जाएगा।
अब मज़े के लिए, कल्पना कीजिए कि जब आप दो फाइलमाइट्स के बीच फ़ाइलों को स्थानांतरित कर रहे हैं तो क्या होता है और आपके पास unlink()
स्रोत से फ़ाइल की अनुमति नहीं है ?
ठीक है, फ़ाइल को पहले गंतव्य पर कॉपी किया जाएगा ( ) read()
, write()
और फिर unlink()
अपर्याप्त अनुमति के कारण विफल हो जाएगा। तो, फाइल दोनों फाइल सिस्टम में रहेगी !!