जब निर्माण के तुरंत बाद बच्चे की प्रक्रिया निष्पादन () या निकास () से कॉल करती है तो vfork () का उपयोग करने का इरादा क्यों है?


11

ऑपरेटिंग सिस्टम कॉन्सेप्ट और APUE कहते हैं

Vfork () के साथ, मूल प्रक्रिया निलंबित है, और बच्चे की प्रक्रिया माता-पिता के पते की जगह का उपयोग करती है। क्योंकि vfork () कॉपी-ऑन-राइट का उपयोग नहीं करता है, अगर बच्चा प्रक्रिया माता-पिता के पते के स्थान के किसी भी पृष्ठ को बदल देता है, तो परिवर्तित पृष्ठ माता-पिता के फिर से शुरू होने पर दिखाई देगा। इसलिए, vfork () का उपयोग सावधानी के साथ किया जाना चाहिए ताकि यह सुनिश्चित हो सके कि बच्चे की प्रक्रिया माता-पिता के पते की जगह को संशोधित नहीं करती है।

vfork () का उपयोग तब किया जाता है जब निर्माण के तुरंत बाद बच्चे की प्रक्रिया निष्पादन () या निकास () से कॉल करती है।

मैं अंतिम वाक्य को कैसे समझूंगा?

जब vfork()कॉल द्वारा बनाई गई एक बाल प्रक्रिया , नए कार्यक्रम को लोड करके, मूल प्रक्रिया के पते की जगह को संशोधित exec()नहीं करती है exec()?

जब vfork()कॉल द्वारा बनाई गई एक बाल प्रक्रिया exit(), exit()बच्चे को समाप्त करते समय माता-पिता की प्रक्रिया के पते की जगह को संशोधित नहीं करती है ?

लिनक्स के लिए मेरी प्राथमिकता है।

धन्यवाद।

जवाबों:


15

जब vfork()कॉल द्वारा बनाई गई एक बाल प्रक्रिया , नए कार्यक्रम को लोड करके, मूल प्रक्रिया के पते की जगह को संशोधित exec()नहीं करती है exec()?

नहीं, exec()नए कार्यक्रम के लिए एक नया पता स्थान प्रदान करता है; यह मूल पता स्थान को संशोधित नहीं करता है। उदाहरण केexec लिए देखें POSIX और लिनक्स execve()मैनपेज में कार्यों की चर्चा

जब vfork () कॉल एक्जिट () द्वारा बनाई गई चाइल्ड प्रोसेस, क्या एग्जिट () पेरेंट प्रोसेस के एड्रेस स्पेस को बच्चे को टर्मिनेट करते समय संशोधित नहीं करती है?

प्लेन exit()हो सकता है - यह रनिंग प्रोग्राम (अपने पुस्तकालयों सहित) द्वारा स्थापित निकास हुक चलाता है। vfork()अधिक प्रतिबंधक है; इस प्रकार, लिनक्स पर, यह उपयोग को अनिवार्य करता है , _exit()जो सी लाइब्रेरी के क्लीन-अप फ़ंक्शन को कॉल नहीं करता है।

vfork()सही होने के लिए काफी मुश्किल निकला; इसे POSIX मानक के वर्तमान संस्करणों में हटा दिया गया है, और posix_spawn()इसके बजाय इसका उपयोग किया जाना चाहिए।

हालाँकि, जब तक आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं, आपको या तो उपयोग नहीं करना चाहिए vfork()या posix_spawn(); अच्छे पुराने fork()और से चिपके रहते हैं exec()

ऊपर लिंक किए गए लिनक्स मैनपेज अधिक संदर्भ प्रदान करता है:

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


धन्यवाद। "निष्पादित () नए कार्यक्रम के लिए एक नया पता स्थान प्रदान करता है;" क्या प्रोग्राम के सामान्य व्यवहार को प्रक्रिया के एड्रेस स्पेस में लोड करना है? मुझे उन दो कड़ियों में नहीं मिला, जहाँ यह सामान्य रूप से या विशेष रूप से vfork () के लिए एक नया पता स्थान बनाता है।
टिम

1
क्या अजीब है vfork () अब सब कुछ के बारे में बस के खिलाफ जीत रहा है। यह हास्यास्पद रूप से कांटा () से तेज है, जब आपके पास एक गीगाबाइट योग्य स्मृति है।
जोशुआ

2
कृपया लोगों को उपयोग करने के लिए न कहें posix_spawnposix_spawnसादे पुराने की तुलना में सही कोड को लिखना काफी कठिन है fork, और यदि आप कोशिश करते हैं, तो आप वहां की ईंट की दीवार में चल सकते हैं, जो फ़ाइल कार्रवाई या विशेषता नहीं है जो उस चीज़ को करता है जो आपको forkऔर उसके बीच की जरूरत है exec। और इसमें vfork जैसी दक्षता होने की गारंटी नहीं है, इसलिए यह उस समस्या को भी हल नहीं करता है जिसे लोग इसे हल करना चाहते हैं।
zwol

1
@zwol: यह वास्तव में बुरी सलाह है। जबकि posix_spawnआप चाहते हैं कि कार्यक्षमता में कमी हो सकती है (आप इसे एक मध्यस्थ सहायक प्रोग्राम के माध्यम से हल कर सकते हैं, जो सी या इनलाइन-ऑन-सेमीडलाइन शेल स्क्रिप्ट में लिखा गया है), जो आप vforkखतरनाक अपरिभाषित व्यवहार के साथ चाहते हैं, उसे प्राप्त करने का कोई भी प्रयास । इसके लिए विनिर्देश vforkबच्चे के लिए राज्य को सेटअप करने से पहले यादृच्छिक कार्यों को कॉल करने की अनुमति नहीं देता है execve, और ऐसा करने का प्रयास माता-पिता की स्थिति को दूषित कर सकता है।
R .. गिटहब स्टॉप हेल्पिंग ICE

1
@ जोशुआ: अधिकांश स्थितियों में आधुनिक कार्यान्वयन posix_spawnसमान रूप से होता है vfork। जहां अंतर होता है, वे बिल्कुल ऐसे मामले होते हैं जहां vforkअत्यधिक असुरक्षित होते हैं: जहां सिग्नल हैंडलर स्थापित होते हैं जिन्हें posix_spawnनिष्पादन से पहले बच्चे में चलने से दबाना पड़ता है।
R .. गिटहब स्टॉप हेल्पिंग ICE

4

जब आप कॉल करते हैं vfork(), तो एक नई प्रक्रिया बनाई जाती है और यह नई प्रक्रिया स्टैक के अपवाद के साथ मूल प्रक्रिया की छवि को उधार लेती है। बच्चे की प्रक्रिया को एक नया स्टैक स्टार दिया जाता है, हालांकि returnउस फ़ंक्शन से अनुमति नहीं देता है जिसे कॉल किया जाता है vfork()

जब बच्चा चल रहा होता है, तो माता-पिता की प्रक्रिया अवरुद्ध हो जाती है, क्योंकि बच्चा माता-पिता के पते की जगह उधार लेता है।

आप जो भी करते हैं, उसके बावजूद जो कुछ भी स्टैक तक पहुंचता है, वह केवल बच्चे के निजी स्टैक को संशोधित करता है। यदि आप हालांकि वैश्विक डेटा को संशोधित करते हैं, तो यह सामान्य डेटा को संशोधित करता है और इस प्रकार यह माता-पिता को भी प्रभावित करता है।

वैश्विक डेटा को संशोधित करने वाली चीजें उदाहरण के लिए हैं:

  • कॉलिंग मॉलोक () या मुफ़्त ()

  • stdio का उपयोग कर

  • सिग्नल सेटिंग्स को संशोधित करना

  • परिवर्तनशील चर जो उस फ़ंक्शन के लिए स्थानीय नहीं हैं जिन्हें कॉल किया गया है vfork()

  • ...

एक बार जब आप कॉल करते हैं _exit()(महत्वपूर्ण, कभी कॉल नहीं करते हैं exit()), तो बच्चे को समाप्त कर दिया जाता है और नियंत्रण वापस माता-पिता को दे दिया जाता है।

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

अभिभावक को नियंत्रण वापस दिया जाता है, क्योंकि यह पता स्थान अब किसी अन्य प्रक्रिया द्वारा उपयोग में नहीं है।

महत्वपूर्ण: लिनक्स पर, कोई वास्तविक vfork()कार्यान्वयन नहीं है। सन 1988 में SunOS-4.0 द्वारा शुरू की गई कांसेप्ट vfork()पर fork()लिखी गई अवधारणा पर आधारित लिनक्स पर लागू होने के बावजूद । उपयोगकर्ताओं को यह विश्वास दिलाने के लिए कि वे उपयोग करते हैं vfork(), लिनक्स सिर्फ साझा किए गए डेटा को सेट करता है और माता-पिता को निलंबित कर देता है, जबकि बच्चा फोन नहीं करता था _exit()या किसी एक exec*()कार्य करता था।

इसलिए लिनक्स इस तथ्य से लाभ नहीं उठाता है कि एक वास्तविक vfork()को कर्नेल में बच्चे के लिए पता स्थान विवरण सेट करने की आवश्यकता नहीं है। इस में परिणाम vfork()तेजी से नहीं है fork()। वास्तविक लागू करने वाली प्रणालियों पर vfork(), यह आमतौर पर की तुलना में तेजी से 3x होता है fork()और उपयोग किए जाने वाले गोले के प्रदर्शन को प्रभावित करता है vfork()- ksh93, हाल ही में Bourne Shellऔर csh

एड चाइल्ड exit()से आपको कभी भी कॉल नहीं करना चाहिए , क्योंकि कॉल करने से पहले फ्लश करने की स्थिति में फ्लश स्टीडियो होता है । इससे अजीब परिणाम हो सकते हैं।vfork()exit()vfork()

BTW: के posix_spawn()शीर्ष पर लागू किया जाता है vfork(), इसलिए vfork()OS से हटाया नहीं जा रहा है। यह उल्लेख किया गया है कि लिनक्स का उपयोग नहीं करता vfork()के लिए posix_spawn()

स्टैक के लिए, कुछ दस्तावेज हैं, यहां सोलारिस मैन पेज कहते हैं:

 The vfork() and vforkx() functions can normally be used  the
 same  way  as  fork() and forkx(), respectively. The calling
 procedure, however, should not return while running  in  the
 child's  context,  since the eventual return from vfork() or
 vforkx() in the parent would be to a  stack  frame  that  no
 longer  exists. 

इसलिए कार्यान्वयन को जो पसंद है वह कर सकता है। Solaris कार्यान्वयन फ़ंक्शन कॉलिंग के स्टैक फ्रेम के लिए साझा मेमोरी का उपयोग करता है vfork()। कोई भी कार्यान्वयन माता-पिता से स्टैक के पुराने हिस्सों तक पहुंच नहीं देता है।


4
न तो GNU C लाइब्रेरी और न ही posix_spawn()Linux के शीर्ष पर musl C लाइब्रेरी लागू है vfork()। वे दोनों इसे शीर्ष पर लागू करते हैं __clone()
JdeBP

1
@ जेडेबीपी: आपको पता है कि vfork()सिर्फ कॉल clone()सही है? यह सचमुच कर्नेल में वन-लाइनर है।
जोशुआ

1
"महत्वपूर्ण: लिनक्स पर, कोई वास्तविक vfork () कार्यान्वयन नहीं है।" <- यह सच नहीं है और कम से कम एक दशक से सच नहीं है। यदि आपका शेल बेंचमार्क लिनक्स के बीच vforkऔर बीच में कोई प्रदर्शन अंतर नहीं देख रहा है fork, तो यह कुछ गलत कर रहा है।
zwol

1
इस उत्तर का दूसरा भाग "महत्वपूर्ण: लिनक्स पर शुरू होता है, कोई वास्तविक vfork () कार्यान्वयन" नहीं है, ज्यादातर या पूरी तरह से गलत है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

1
कृपया सत्यापन किए बिना दावे न करें। वर्तमान बॉर्न शेल को vfork समर्थन के साथ और बिना संकलित किया जा सकता है, इसलिए यदि आप मानते हैं कि लिनक्स से डीबगिंग सुविधाएँ विश्वसनीय परिणाम देने में असमर्थ हैं, तो आप शेल में vfork के साथ और उसके साथ कॉन्फ़िगर कॉल के लिए निष्पादन समय की तुलना कर सकते हैं। मैं 800 परीक्षणों के साथ एक कॉन्फ़िगर स्क्रिप्ट का उपयोग करता हूं। सोलारिस पर, फोर्क केस की तुलना में vfork का उपयोग करने वाले बॉर्न शेल को 30% कम सिस्टम सीपीयू समय की आवश्यकता होती है। लिनक्स पर, एक ही परीक्षा परिणाम 10% से कम सिस्टम सीपीयू समय में आता है। सोलारिस पर यह 3x नहीं है क्योंकि इसमें कई संकलक कॉल शामिल हैं।
स्किल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.