2010-11-23 9 views
26

fork() और vfork() के बीच क्या अंतर है? vfork()fork() की तरह वापसी करता है।फोर्क() और vfork() के बीच क्या अंतर है?

+4

* कांटा * का अर्थ असली कर्नल पर कार्य है। * vfork * असली कर्नेल पर जोरदार कार्यों का मतलब है। – tchrist

उत्तर

30

vfork की मंशा पूरी प्रक्रिया छवि को कॉपी अगर आप केवल बच्चे में एक exec* क्या करना चाहते हैं की भूमि के ऊपर समाप्त करने के लिए किया गया था। चूंकि exec* बाल प्रक्रिया की पूरी छवि को प्रतिस्थापित करता है, इसलिए माता-पिता की छवि की प्रतिलिपि बनाने में कोई बात नहीं है।

if ((pid = vfork()) == 0) { 
    execl(..., NULL); /* after a successful execl the parent should be resumed */ 
    _exit(127); /* terminate the child in case execl fails */ 
} 

का उपयोग करता है के अन्य प्रकार के लिए, vfork खतरनाक और अप्रत्याशित है।

लिनक्स समेत अधिकांश मौजूदा कर्नेल के साथ vfork का प्राथमिक लाभ गायब हो गया है क्योंकि fork लागू किया गया है। fork निष्पादित होने पर पूरी छवि की प्रतिलिपि बनाने की बजाय, कॉपी-ऑन-राइट तकनीकों का उपयोग किया जाता है।

+1

बीएसडी-आधारित सिस्टमों में अभी भी एक वास्तविक * vfork * फ़ंक्शन है। स्रोत पढ़ें। – tchrist

+6

लिनक्स भी एक असली 'vfork (2) 'है। आम तौर पर, मुझे लगता है कि प्रत्येक * निक्स जिसे गैर-एमएमयू प्लेटफॉर्म पर पोर्ट किया गया है, वास्तविक 'vfork (2) 'है। – ninjalj

+2

नोट करने के लिए महत्वपूर्ण * कॉपी-ऑन-राइट तकनीक *। मेमोरी केवल तभी कॉपी हो जाती है जब नई प्रक्रिया इसे संशोधित करने का प्रयास करती है। एंड्रॉइड जैसे सिस्टम के लिए बहुत महत्वपूर्ण है। –

4
मेरा आदमी पृष्ठ से

(POSIX.1 से) vfork() फ़ंक्शन कांटा जैसा ही होता है (2), छोड़कर व्यवहार अपरिभाषित है कि प्रक्रिया द्वारा बनाई गई है, तो vfork() या तो pid_t के एक चर के अलावा किसी भी डेटा को संशोधित करता है जो vfork() से वापसी मान को संग्रहीत करने के लिए उपयोग किया जाता है, या फ़ंक्शन से लौटाता है जिसमें vfork() कहा जाता है, या सफलतापूर्वक कॉल करने से पहले किसी भी अन्य फ़ंक्शन पर कॉल करता है _exit (2) या निष्पादन में से एक (3) fam कार्यों का ily।

vfork() में कांटा (2) से अलग है कि जब तक बच्चे समाप्त हो जाता है माता पिता निलंबित कर दिया है (या तो सामान्य रूप से, से बुला _exit (2), या असामान्य रूप से, एक घातक संकेत के प्रसव के बाद), या यह निष्पादित करने के लिए कॉल करता है (2)। उस बिंदु तक, बच्चे सभी स्मृति को के साथ अपने माता-पिता को ढेर समेत साझा करता है। बच्चे को वर्तमान फ़ंक्शन या कॉल एक्जिट (3), से से वापस नहीं लौटना चाहिए, लेकिन _exit (2) को कॉल कर सकता है।

+0

+1 आरटीएफ मैन पेज। इसके अलावा, xkcd लिंक xkcd के बाद * हर * SO प्रश्न के लिए कॉमिक है: http://xkcd.org/293 – delnan

+2

यह भी ध्यान देने योग्य है कि 'vfork() 'ज्यादातर ऐतिहासिक आर्टिफैक्ट है - आधुनिक सिस्टम पर सैन कॉपी-ऑन -राइट अर्थशास्त्र, 'vfork() 'आमतौर पर आपको अधिक लाभ नहीं मिलता है (यदि कुछ भी हो, कभी-कभी यह अनिवार्य रूप से' कांटा()' के लिए उपनाम है!)। –

0

here देखें और wikipedia से -

कुछ सिस्टम पर, vfork() एक ही है कांटा के रूप में()। Vfork() फ़ंक्शन केवल फोर्क() से भिन्न होता है जिसमें बाल प्रक्रिया कॉलिंग प्रक्रिया के साथ कोड और डेटा साझा कर सकती है (पैरेंट प्रक्रिया)।

18

जैसा कि पहले से ही कहा गया है, vfork मैन पेज अंतर के बारे में स्पष्ट है। यह topicfork, vfork, clone और exec का अच्छा विवरण देता है।

नीचे fork और vfork के बीच कुछ अनदेखी मतभेद नीचे दिए गए हैं, मैंने कुछ लिनक्स 2.6.3x एम्बेडेड सिस्टम पर अनुभव किया है जिनके साथ मैंने काम किया था।

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

vfork में यह स्मृति समस्या नहीं है, क्योंकि यह मूल पता स्थान को डुप्लिकेट नहीं करता है। बाल प्रक्रिया एक थ्रेड की तरह काम करती है जिसमें आप अपनी पेरेंट प्रक्रिया को चोट पहुंचाए बिना exec* या _exit पर कॉल करने में सक्षम हैं।

क्योंकि स्मृति पृष्ठ सारणी दोहराया नहीं कर रहे हैं, vforkfork की तुलना में बहुत तेजी से होता है और जैसा कि यहाँ बताया vfork के निष्पादन समय, स्मृति की मात्रा माता पिता प्रक्रिया का उपयोग करता से प्रभावित नहीं है: http://blog.famzah.net/2009/11/20/fork-gets-slower-as-parent-process-use-more-memory/

स्थितियों में, जहां में प्रदर्शन महत्वपूर्ण है और/या स्मृति सीमित है, vfork + exec* इसलिए fork + exec* के लिए एक अच्छा विकल्प हो सकता है। समस्या यह है कि यह कम सुरक्षित है और मैन पेज का कहना है कि vfork भविष्य में बहिष्कृत होने की संभावना है।

posix_spawn फ़ंक्शन पर एक सुरक्षित और अधिक पोर्टेबल समाधान हो सकता है, जो उच्च स्तर है और अधिक विकल्प प्रदान करता है। जब आप इसे पारित करने के विकल्पों पर निर्भर करते हैं, तो यह सुरक्षित रूप से vfork का उपयोग करता है। मैं posix_spawn सफलतापूर्वक उपयोग करने में सक्षम हूं और उस परेशान "डबल मेमोरी जांच समस्या" को दूर करता हूं जो fork + exec मुझे दे रहा था।

A really good page on this topic, with links to some posix_spawn examples.

+2

संयोग से, जावा के 'Runtime.exec() 'ने पारंपरिक रूप से' कांटा()/exec()' का उपयोग किया है, लेकिन आईआईआरसी जावा 1.7 'vfork()/exec() 'या' posix_spawn() 'उपलब्ध होगा जहां उपलब्ध है। – ninjalj

2

कुछ प्रणालियों एक सिस्टम कॉल vfork(), जो मूल रूप कांटा के एक कम भूमि के ऊपर संस्करण के रूप में डिजाइन किया गया था है()। चूंकि कांटा() प्रक्रिया के पूरे पता स्थान की प्रतिलिपि बनाने में शामिल है, और इसलिए काफी महंगा था, vfork() फ़ंक्शन पेश किया गया था (3.0BSD में)।

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

नतीजतन, फोर्क() और vfork() के बीच वास्तव में किसी भी अंतर का उपयोग करना बहुत मूर्ख नहीं है। दरअसल, शायद vfork() का उपयोग करना मूर्ख नहीं है, जब तक कि आप बिल्कुल नहीं जानते कि आप क्यों चाहते हैं।

दोनों के बीच मूल अंतर यह है कि जब vfork() के साथ एक नई प्रक्रिया बनाई जाती है, तो मूल प्रक्रिया अस्थायी रूप से निलंबित कर दी जाती है, और बच्चे की प्रक्रिया माता-पिता की पता स्थान उधार ले सकती है। मामलों की यह अजीब स्थिति तब तक जारी है जब तक बच्चे की प्रक्रिया या तो बाहर निकलती है, या कॉल निष्पादित करती है(), जिस बिंदु पर मूल प्रक्रिया जारी है।

इसका मतलब है कि एक vfork() की बाल प्रक्रिया को माता-पिता प्रक्रिया के अप्रत्याशित रूप से संशोधित चर से बचने के लिए सावधान रहना चाहिए।विशेष रूप से, बच्चे की प्रक्रिया vfork() कॉल वाले फ़ंक्शन से वापस नहीं आनी चाहिए, और इसे बाहर निकलने की आवश्यकता नहीं है() (अगर इसे बाहर निकलने की आवश्यकता है, तो इसे _exit() का उपयोग करना चाहिए; असल में, यह बच्चे के लिए भी सच है एक सामान्य कांटा())।

0

दोनों के बीच मूल अंतर यह है कि जब vfork() के साथ एक नई प्रक्रिया बनाई जाती है, तो मूल प्रक्रिया अस्थायी रूप से निलंबित कर दी जाती है, और बाल प्रक्रिया माता-पिता की पता स्थान उधार ले सकती है। यह अजीब स्थिति तब तक जारी है जब तक कि बच्चे की प्रक्रिया या तो बाहर निकलती है, या execve() पर कॉल करती है, जिस बिंदु पर मूल प्रक्रिया जारी है।

इसका मतलब है कि vfork() की बाल प्रक्रिया को पर सावधान रहना चाहिए, जो मूल प्रक्रिया के अप्रत्याशित रूप से संशोधित चर से बचें। विशेष रूप से, बच्चे प्रक्रिया समारोह vfork() कॉल युक्त से वापस नहीं आना चाहिए, और यह exit() फोन नहीं करना चाहिए (अगर यह बाहर निकलने की जरूरत है, यह का उपयोग करना चाहिए _exit(); वास्तव में, यह भी सच है कि एक सामान्य की बच्चे के लिए है fork())।

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

नतीजतन, fork() और vfork() के बीच वास्तव में अंतरों का उपयोग करना बहुत मूर्ख नहीं है। दरअसल, शायद vfork() का उपयोग करने के लिए मूर्ख नहीं है, जब तक कि आप बिल्कुल क्यों नहीं जानते हैं।

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