2013-02-19 76 views
6

मैं क्लोज-टू-ओएस प्रोग्रामिंग तकनीकों में शामिल नहीं हूं, लेकिन जैसा कि मुझे पता है, जब पर्ल में समानांतर में कुछ करने की बात आती है तो पसंद के हथियार fork और संभवतः कुछ उपयोगी मॉड्यूल बनाए जाते हैं। fork के लिए डॉक पेज का कहना है:स्वतंत्र रूप से चलाने के लिए कोड के केवल एक हिस्से को अलग करने के लिए पर्ल तकनीक क्या हैं?

Does a fork(2) system call to create a new process running the same program at the same point. 

परिणामस्वरूप, एक बड़ा अनुप्रयोग है कि स्मृति का एक बहुत और एक छोटे से कार्य के लिए fork बुला खपत वहाँ 2 बड़े पर्ल प्रक्रियाओं हो जाएगा मतलब है होने, और दूसरा संसाधनों बर्बाद करेंगे बस कुछ सरल काम करने के लिए।

तो, सवाल यह है: (या कैसे fork उपयोग करने के लिए, अगर यह एकमात्र तरीका है) क्या करना है क्रम स्वतंत्र रूप से और चल रहा कोड का एक अलग हिस्से में काफ़ी सिर्फ संसाधनों यह की जरूरत है पाने के लिए?

बस एक बहुत simpel उदाहरण:

use strict; 
    use warnings; 

    my @big_array = (1 .. 2000000); # at least 80 MB memory 
    sleep 10; # to have time to inspect easely the memory usage 

    fork(); 
    sleep 10; # to have time to inspect easely the memory usage 

और बच्चे प्रक्रिया की खपत 80 + एमबी भी।

स्पष्ट है: यह इस अलग कोड के लिए बातचीत करने के लिए महत्वपूर्ण नहीं है या किसी भी तरह उसके परिणाम का उपयोग करने के लिए, बस "कहने के लिए हे संभव हो सकता है, मेरे लिए पृष्ठभूमि में इस सरल कार्य चलाने के लिए और मुझे आगे बढ़ें मेरी इस बीच भारी काम ... और मेरे संसाधनों को बर्बाद मत करो! "भारी पर्ल आवेदन चलाते समय।

+0

एक बाल प्रक्रिया अपने सभी माता-पिता के गुणों का वारिस करेगी। फोकिंग के साथ घूमने का कोई वास्तविक तरीका नहीं है, मुझे नहीं लगता। – squiguy

+0

'कांटा' का उपयोग करना अनिवार्य नहीं है। कोई भी तकनीक स्वीकार्य होगी, यहां तक ​​कि 'सिस्टम' को भी बुलाएगी। – ArtM

उत्तर

3

fork() से exec() यहां आपकी बनी है। fork() एक नई प्रक्रिया बनाने के लिए (जो एक काफी सस्ता ऑपरेशन है, नीचे देखें), फिर exec() को बड़े perl को बदलने के लिए आप कुछ छोटे से चल रहे हैं। यह इस तरह दिखता है:

use strict; 
use warnings; 
use 5.010; 

my @ary = (1 .. 10_000_000); 

if (my $pid = fork()) { 
    # parent 
    say "Forked $pid from $$; sleeping"; 
    sleep 1_000; 
} else { 
    # child 
    exec('perl -e sleep 1_000'); 
} 

(@ary सिर्फ मूल प्रक्रिया 'स्मृति थोड़ा को भरने के लिए इस्तेमाल किया गया था।)

मैंने कहा कि fork() आईएनजी अपेक्षाकृत सस्ता था, भले ही यह पूरी मूल प्रक्रिया की प्रतिलिपि बनाता है। ये बयान संघर्ष में नहीं हैं; fork डिज़ाइन किए गए लोग इस समस्या को देखते हैं। प्रति आलसी आलसी है, यानी, केवल बिट्स जो वास्तव में बदली जाती हैं, की प्रतिलिपि बनाई जाती है।

यदि आप पाते हैं कि आप प्रक्रियाओं को एक दूसरे से बात करना चाहते हैं, तो आप आईपीसी के अधिक जटिल डोमेन में शामिल होना शुरू कर देंगे, जिसके बारे में कई किताबें लिखी गई हैं।

+0

में 'ps' के बजाय यह 'शीर्ष' होना चाहिए, यह 'exec()' को कॉल करने से पहले बहुत कम समय के लिए स्मृति की प्रतिलिपि बना सकता है और फिर बच्चे को समाप्त होने के बाद स्मृति को मुक्त कर सकता है? और आखिरकार, अगर सब कुछ सिस्टम/निष्पादन को कॉल करने के लिए अभिसरण करता है, तो इसे कांटा का उपयोग करने की भी आवश्यकता नहीं है :) .. ठीक है, 'exec' के लिए यह आवश्यक है, लेकिन' सिस्टम ('... &');' अच्छी तरह से काम करता है – ArtM

+2

@ArtM जैसा कि कहा गया है, यह आलसी प्रतिलिपि है। और 'सिस्टम (' ... & ') '* *' कांटा() 'के बाद' exec()' है, जिसमें केवल ग्रिन्स के लिए मध्य में फंस गया खोल है और बूट करने के लिए एक और अधिक नाजुकता। इसे करने के एक से अधिक तरीके, वहाँ है; मेरा तरीका बेहतर मुझे पसंद है। – darch

+1

लिनक्स पर पीआईडी> 1 के साथ हर प्रक्रिया को एक कांटा (शुरुआत में init) के माध्यम से बनाया जाता है। उदाहरण के लिए, यदि आप दौड़ते हैं आपके टर्मिनल में कुछ, बैश (या जो कुछ भी) इसे निष्पादित करने के लिए फोर्क करेगा। कॉपी-ऑन-राइट सेमेन्टिक्स यह सुनिश्चित करता है कि यह कुशल है। – rjh

1

अपनी प्रक्रिया के पदचिह्न के किसी उप सेट कांटा करने के लिए कोई तरीका नहीं है, तो हमेशा की तरह समाधान करने के लिए नीचे आ:

  1. fork इससे पहले कि आप माता-पिता की प्रक्रिया में स्मृति गहन कोड चलाने
  2. एक अलग प्रक्रिया शुरू
  3. system या open HANDLE,'|-',... के साथ। बेशक यह नई प्रक्रिया अपने माता-पिता से किसी भी डेटा का वारिस नहीं करेगी, इसलिए आपको किसी भी तरह से इस बच्चे को डेटा पास करने की आवश्यकता होगी।
3

आपकी फोर्क प्रक्रिया वास्तव में 80 एमबी निवासी स्मृति का उपयोग नहीं कर रही है। उस स्मृति का एक बड़ा हिस्सा साझा किया गया - अभिभावक प्रक्रिया से 'उधार' जब तक माता-पिता या बच्चे इसे लिखते हैं, उस बिंदु पर कॉपी-ऑन-राइट अर्थशास्त्र स्मृति को वास्तव में कॉपी करने का कारण बनेंगे।

यदि आप उस सामान को पूरी तरह से छोड़ना चाहते हैं, तो अपने फोर्क में exec चलाएं। इससे बाल पर्ल प्रक्रिया को एक अलग निष्पादन योग्य के साथ बदल दिया जाएगा, इस प्रकार स्मृति को मुक्त किया जा सकेगा। यह भी सही है अगर आपको माता-पिता को कुछ भी संवाद करने की आवश्यकता नहीं है।

+0

सुनिश्चित नहीं है कि शब्दावली चर * साझा * हैं। मुझे इन मानों को 'ps' के लिए आरईएस/एसएचआर कॉलम के तहत मिलता है जबकि दोनों प्रक्रियाएं चल रही हैं: 48 एम/1776 और 46 एम/156 (1 एम सरणी तत्व)। – ArtM

+0

क्षमा करें, उपर्युक्त टिप्पणी – ArtM

1

fork() अधिकांश ऑपरेटिंग सिस्टम पर लागू होने के रूप में अच्छी तरह से कुशल है। यह आम तौर पर कॉपी-ऑन-राइट नामक तकनीक का उपयोग करता है, इसका मतलब यह है कि पृष्ठ प्रारंभ में तब तक साझा किए जाते हैं जब तक कि एक या अन्य प्रक्रिया उन्हें लिखती नहीं है। इसके अलावा आपकी बहुत सी प्रक्रिया मेमोरी को वैसे भी मैप की गई फ़ाइलों को पढ़ा जा रहा है।

सिर्फ इसलिए कि fork() से पहले एक प्रक्रिया 80 एमबी का उपयोग करती है इसका मतलब यह नहीं है कि बाद में दोनों 160 का उपयोग करेंगे। इसके साथ शुरू करने के लिए केवल 80 एमबी से अधिक छोटा अंश होगा, जब तक कि प्रत्येक प्रक्रिया अधिक पृष्ठों को गंदे शुरू न करे।

+0

मुझे लगता है कि यह तब तक होना चाहिए जब तक कि कम से कम एक प्रक्रिया गंदगी शुरू नहीं हो जाती ... * या तर्कसंगत रूप से समकक्ष इसके लिए। ठीक है, यह 'मेरा @big = (1 .. 1000000)' सिर्फ एक साधारण जेनेरिक उदाहरण कोड है, यह अधिक जटिल और बाहरी ओवीएम smth हो सकता है पूरे कोड स्पेस एर करें। और आपके हस्तक्षेप के लिए धन्यवाद। – ArtM