2012-12-04 30 views
5

अभी मैं एक सी प्रोग्राम लिख रहा हूं जिसे बाल प्रक्रिया को निष्पादित करना होगा। मैं एक साथ कई बच्चे प्रक्रियाओं को नहीं कर रहा हूं, इसलिए यह काफी सरल है। मैं निश्चित रूप से अंतर्निहित शैल प्रोग्राम (यानी बिल्ली और गूंज जैसी चीजें) को सफलतापूर्वक निष्पादित कर रहा हूं, लेकिन मुझे यह बताने में भी सक्षम होना चाहिए कि इनमें से कोई प्रोग्राम सफलतापूर्वक निष्पादित करने में विफल रहता है। मैं निम्नलिखित सरल कोड के साथ इस कोशिश कर रहा हूँ:execvp/कांटा - असफल निष्पादन कैसे प्राप्त करें?

int returnStatus; // The return status of the child process. 
pid_t pid = fork(); 

if (pid == -1) // error with forking. 
{ 
    // Not really important for this question. 
} 
else if (pid == 0) // We're in the child process. 
{ 
    execvp(programName, programNameAndCommandsArray); // vars declared above fork(). 

    // If this code executes the execution has failed. 
    exit(127); // This exit code was taken from a exec tutorial -- why 127? 
} 
else // We're in the parent process. 
{ 
    wait(&returnStatus); // Wait for the child process to exit. 

    if (returnStatus == -1) // The child process execution failed. 
    { 
     // Log an error of execution. 
    } 
} 

इसलिए उदाहरण के लिए, अगर मैं rm fileThatDoesntExist.txt निष्पादित करने के लिए प्रयास करते हैं, मैं विचार करने के लिए है कि फाइल के बाद से एक विफलता मौजूद नहीं था चाहते हैं। मैं यह कैसे हासिल कर सकता हूं? साथ ही, जबकि execvp() कॉल सफलतापूर्वक अंतर्निहित शैल प्रोग्राम निष्पादित करता है, यह निष्पादन योग्य की वर्तमान निर्देशिका में प्रोग्राम निष्पादित नहीं करता है (यानी वह प्रोग्राम जो इस कोड के अंदर चल रहा है); क्या वर्तमान निर्देशिका में प्रोग्राम चलाने के लिए मुझे कुछ और करना है?

धन्यवाद!

+0

संभावित डुप्लिकेट [फोर्क()) के बाद execvp (...) त्रुटियों को कैसे संभालें? (Https: // stackoverflow।कॉम/प्रश्न/1584956/कैसे-टू-हैंडल-execvp-error-after-fork) – Ruslan

उत्तर

13

यह एक बहुत ही सुरुचिपूर्ण समाधान के साथ एक क्लासिक समस्या है। फोर्किंग से पहले, माता-पिता में pipe बनाएं। fork के बाद, माता-पिता को पाइप के लेखन अंत को बंद करना चाहिए, और पढ़ने के अंत से read पर प्रयास करना बंद कर देना चाहिए। बच्चे को पढ़ने के अंत के लिए fcntl का उपयोग करके, पढ़ने के अंत को बंद करना चाहिए और क्लोज-ऑन-निष्पादन ध्वज सेट करना चाहिए।

अब, अगर बच्चे execvp सफलतापूर्वक कहता है, पाइप के लेखन अंत कोई डेटा के साथ बंद कर दिया जाएगा, और माता पिता में read 0. वापस आ जाएगी execvp बच्चे में विफल रहता है, पाइप के लिए त्रुटि कोड लिखते हैं, और माता-पिता में read अभिभावक को संभालने के लिए त्रुटि कोड पढ़ने के बाद, nonzero वापस कर देगा।

+0

टिप्पणी के लिए धन्यवाद, यह निश्चित रूप से मुझे सही रास्ते पर प्राप्त कर लिया है। कुछ और शोध के बाद मुझे एहसास हुआ कि मुझे केवल बाल प्रक्रिया के stderr आउटपुट को कैप्चर करने की परवाह है। मुझे लगता है कि मैं सिर्फ यह जांचूंगा कि क्या स्टडर खाली है या नहीं और यह निर्धारित करने के लिए पर्याप्त होगा कि निष्पादन के साथ कोई समस्या थी। हालांकि, मुझे इस विचार को कोड में बदलने में परेशानी हो रही है। क्या इसमें डुप्ली() को कॉल करना शामिल होगा? –

0

विफलता का पता लगाने के मामले में, यदि कोई exec() फ़ंक्शन वर्तमान प्रक्रिया को एक नए के साथ बदल देता है, तो वर्तमान प्रक्रिया समाप्त हो जाती है; इससे कोई फर्क नहीं पड़ता कि निष्पादित कार्यक्रम यह तय करता है कि जो करने के लिए कहा गया है वह सफलता या विफलता है। हालांकि, कांटे से पहले की मूल प्रक्रिया बच्चे के निकास कोड को खोज सकती है जिसमें कमांड सफलता/विफलता की जानकारी होगी।

निष्पादन योग्य खोजने के मामले में, execvp() वर्तमान पथ को खोजकर, खोल की क्रिया को डुप्लिकेट करता है। यदि यह कार्यशील निर्देशिका में निष्पादन योग्य नहीं ढूंढ रहा है, तो संभव है कि निर्देशिका खोज पथ में नहीं है (या फ़ाइलें वास्तव में निष्पादन योग्य नहीं हैं)। आप उन्हें पूर्ण पथ नाम से निर्दिष्ट करने का प्रयास कर सकते हैं।

यदि आप बस एक आदेश चलाने के लिए चाहते हैं और परिणाम की प्रतीक्षा कर रहे हैं, तो आप सिस्टम() फ़ंक्शन का उपयोग करना चाहेंगे जो इसे आपके लिए फोर्क/निष्पादन के साथ बनाने के बजाय संभालता है।

+0

अच्छी जानकारी, लेकिन माता-पिता के लिए 'execvp' विफल होने और nonzero निकास स्थिति से बाहर निकलने वाले बाहरी प्रोग्राम के बीच अंतर करने के लिए पर्याप्त नहीं है। –

+0

@R - अगर execvp() का उपयोग करते हैं, तो मूल प्रक्रिया को चलाने के लिए एकमात्र तरीका यह है कि execvp विफल रहता है, जिस बिंदु पर आप माता-पिता को सूचित कर सकते हैं। यदि सिस्टम() का उपयोग करना विफलताओं को अलग करने के तरीके को समझने में कुछ जांच ले सकता है। –

+0

माता-पिता को सूचित करना मुश्किल हिस्सा है। मेरा जवाब बताता है कि यह कैसे करें। –

3

wait(2) आपको बाल प्रक्रिया की निकास स्थिति से अधिक देता है। असली निकास स्थिति प्राप्त करने के लिए, आपको WIFEXITED() मैक्रो का उपयोग करने के लिए परीक्षण करना होगा यदि बच्चा सामान्य रूप से बाहर निकलता है (जैसा कि असामान्य रूप से सिग्नल इत्यादि के माध्यम से होता है), और फिर वास्तविक निकास स्थिति प्राप्त करने के लिए WEXITSTATUS() मैक्रो का उपयोग करें:

wait(&status); 
if(WIFEXITED(status)) 
{ 
    if(WEXITSTATUS(status) == 0) 
    { 
     // Program succeeded 
    } 
    else 
    { 
     // Program failed but exited normally 
    } 
} 
else 
{ 
    // Program exited abnormally 
} 

execvp(3) के लिए आदेश वर्तमान निर्देशिका में एक कार्यक्रम चलाने के लिए, आप या तो अपने $PATH पर्यावरण के लिए वर्तमान निर्देशिका जोड़ने के लिए (आमतौर पर नहीं एक अच्छा विचार है), या इसे पूरा पथ, जैसे उत्तीर्ण करनी myprogram के बजाय ./myprogram का उपयोग करें।

+2

यह जानकारी सभी सही है, लेकिन यह आपको नहीं बता सकती कि 'execvp' सफल हुआ है या नहीं। –

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

  • कोई संबंधित समस्या नहीं^_^