linux - निष्पादन का समय बर्बाद() और कांटा()




unix operating-system (4)

इस कॉम्बो (कुछ अन्य समाधान के बजाय) का उपयोग करके क्या लाभ है जो लोगों को अभी भी इसका उपयोग करता है भले ही हमारे पास बेकार है?

आपको किसी तरह एक नई प्रक्रिया बनानी होगी। एक उपयोगकर्ता कार्यक्रम को पूरा करने के लिए बहुत कम तरीके हैं। POSIX में vfork() alognside fork() उपयोग किया जाता था, और कुछ प्रणालियों के पास अपने स्वयं के तंत्र हो सकते हैं, जैसे कि Linux-specific clone() , लेकिन 2008 के बाद से, POSIX केवल fork() और posix_spawn() परिवार निर्दिष्ट करता है। fork + exec मार्ग अधिक पारंपरिक है, अच्छी तरह से समझा जाता है, और इसमें कुछ कमियां हैं (नीचे देखें)। posix_spawn परिवार को संदर्भों में उपयोग के लिए एक विशेष उद्देश्य के विकल्प के रूप में डिज़ाइन किया गया है जो fork() लिए कठिनाइयों को प्रस्तुत करता है; आप इसके विनिर्देशन के "Rationale" अनुभाग में विवरण पा सकते हैं।

vfork() लिए लिनक्स मैन पेज से यह अंश प्रकाशित हो सकता है:

लिनक्स के तहत, fork (2) कॉपी-ऑन-राइट पृष्ठों का उपयोग करके कार्यान्वित किया जाता है, इसलिए fork (2) द्वारा लगाया जाने वाला एकमात्र जुर्माना माता-पिता की पेज तालिकाओं की नकल करने और बच्चे के लिए एक अद्वितीय कार्य संरचना बनाने के लिए आवश्यक समय और मेमोरी है। । हालांकि, बुरे पुराने दिनों में एक fork (2) को कॉलर के डेटा स्थान की पूरी प्रतिलिपि बनाने की आवश्यकता होती है, अक्सर अनावश्यक रूप से, क्योंकि आमतौर पर तुरंत बाद एक exec (3) किया जाता है। इस प्रकार, अधिक दक्षता के लिए, बीएसडी ने vfork () सिस्टम कॉल की शुरुआत की, जो मूल प्रक्रिया के पते के स्थान को पूरी तरह से कॉपी नहीं करता था, लेकिन माता-पिता की स्मृति और नियंत्रण के धागे को उधार लिया (2) या execve करने के लिए कॉल आने तक। माता-पिता की प्रक्रिया को निलंबित कर दिया गया था, जबकि बच्चा अपने संसाधनों का उपयोग कर रहा था। vfork () का उपयोग मुश्किल था: उदाहरण के लिए, माता-पिता की प्रक्रिया में डेटा को संशोधित नहीं करना यह जानने पर निर्भर करता है कि कौन से चर एक रजिस्टर में रखे गए हैं।

(महत्व दिया)

इस प्रकार, कचरे के बारे में आपकी चिंता आधुनिक प्रणालियों (लिनक्स तक सीमित नहीं) के लिए अच्छी तरह से स्थापित नहीं है, लेकिन यह वास्तव में ऐतिहासिक रूप से एक मुद्दा था, और इससे बचने के लिए वास्तव में तैयार किए गए तंत्र थे। इन दिनों, उन तंत्रों में से अधिकांश अप्रचलित हैं।

मैं वर्तमान में fork() और execv() बारे में सीख रहा हूं और मेरे पास संयोजन की दक्षता के बारे में एक प्रश्न था।

मुझे निम्न मानक कोड दिखाया गया था:

pid = fork();
if(pid < 0){
    //handle fork error
}
else if (pid == 0){
    execv("son_prog", argv_son);
//do father code

मुझे पता है कि fork() संपूर्ण प्रक्रिया (संपूर्ण ढेर की नकल करना, आदि fork() क्लोन करता है और नए प्रोग्राम के साथ वर्तमान पता स्थान को execv() करता है। इसे ध्यान में रखते हुए, क्या यह इस संयोजन का उपयोग करने में अक्षम नहीं है? हम एक प्रक्रिया के पूरे पता स्थान की प्रतिलिपि बना रहे हैं और फिर इसे तुरंत अधिलेखित कर देते हैं।

तो मेरा सवाल:
इस कॉम्बो (कुछ अन्य समाधान के बजाय) का उपयोग करके क्या लाभ है जो लोगों को अभी भी इसका उपयोग करता है, भले ही हमारे पास अपशिष्ट हो?


एक अन्य उत्तर में कहा गया है:

हालांकि, बुरे पुराने दिनों में एक कांटा (2) को कॉलर के डेटा स्थान की पूरी प्रतिलिपि बनाने की आवश्यकता होती है, अक्सर अनावश्यक रूप से, क्योंकि आमतौर पर तुरंत बाद एक निष्पादन (3) किया जाता है।

जाहिर है, एक व्यक्ति के बुरे पुराने दिन दूसरों की याद करने की तुलना में बहुत कम हैं।

मूल UNIX सिस्टम में कई प्रक्रियाओं को चलाने के लिए मेमोरी नहीं थी और उनके पास एक ही लॉजिकल एड्रेस स्पेस में रेडी-टू-रन के लिए कई प्रक्रियाओं को रखने के लिए MMU नहीं था: उन्होंने डिस्क को प्रोसेस करने के लिए स्वैप किया जो कि यह नहीं था अभी चल रही।

फोर्क सिस्टम कॉल लगभग पूरी तरह से डिस्क को चालू करने के लिए था, वापसी मूल्य को छोड़कर और अन्य प्रक्रिया में स्वैप करके शेष इन-मेमोरी कॉपी को प्रतिस्थापित नहीं करने के लिए। चूँकि आपको बच्चे को चलाने के लिए किसी भी तरह से मूल प्रक्रिया को स्वैप करना था, कांटा + निष्पादन किसी भी ओवरहेड को नहीं कर रहा था।

यह सच है कि एक समय था जब कांटा + निष्पादन अजीब था: जब MMUs थे जो तार्किक और भौतिक पता स्थान के बीच मानचित्रण प्रदान करते थे, लेकिन पृष्ठ दोष पर्याप्त जानकारी को बनाए नहीं रखते थे जो कॉपी-ऑन-राइट और कई अन्य आभासी थे -मोरोरी / डिमांड-पेजिंग योजनाएं व्यवहार्य थीं।

यह स्थिति काफी दर्दनाक थी, न कि केवल UNIX के लिए, हार्डवेयर के पृष्ठ दोष से निपटने के लिए "रिप्लेसेबल" बहुत तेजी से बनने के लिए अनुकूलित किया गया था।


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


यह उन सभी गाय पृष्ठ दोषों को बाहर कर देता है, जब प्रक्रिया में कुछ गीगाबाइट्स की कमी नहीं होती है। वे सभी एक बार गलती कर रहे हैं भले ही बच्चे को लंबे समय से exec() कहा जाता है। क्योंकि fork() के बच्चे fork() को अब सिंगल थ्रेडेड केस के लिए भी मेमोरी आवंटित करने की अनुमति नहीं है (आप उस के लिए Apple को धन्यवाद दे सकते हैं), इसके बजाय vfork()/exec() को कॉल करने की व्यवस्था करना अब शायद ही मुश्किल है।

vfork()/exec() मॉडल का वास्तविक लाभ यह है कि आप बच्चे को एक मनमाना वर्तमान निर्देशिका, मनमाना पर्यावरण चर, और मनमाने ढंग से fs हैंडल (न केवल stdin/stdout/stderr ), एक मनमाना सिग्नल मास्क, और सेट कर सकते हैं कुछ मनमानी साझा मेमोरी (साझा मेमोरी syscalls का उपयोग) एक बीस-तर्क CreateProcess() API के बिना जो हर कुछ वर्षों में कुछ और तर्क प्राप्त करता है।

यह "उफ़ मैं लीक हुआ हैंडल एक और धागे द्वारा खोला जा रहा है" निकला, थ्रेडिंग के शुरुआती दिनों से गैफ़ उपयोगकर्ताओं / w / o प्रक्रिया-वाइड लॉकिंग /proc के लिए उपयुक्त था। वही नए OS संस्करण के बिना विशाल CreateProcess() मॉडल में नहीं होगा, और नए API को कॉल करने के लिए हर किसी को आश्वस्त करेगा।

इसलिए यह अब आपके पास है। डिजाइन का एक हादसा सीधे तैयार किए गए समाधान की तुलना में कहीं बेहतर समाप्त हुआ।





fork