2008-09-16 22 views
7

मुझे अपने C प्रोग्राम के भीतर से एक और प्रोग्राम कैसे चलाया जाना चाहिए? मुझे लॉन्च प्रोग्राम के STDIN में डेटा लिखने में सक्षम होना चाहिए (और शायद इसे STDOUT से पढ़ें)सी प्रोग्राम के भीतर से प्रोग्राम निष्पादित करें

मुझे यकीन नहीं है कि यह एक मानक सी फ़ंक्शन है या नहीं। मुझे उस समाधान की आवश्यकता है जो लिनक्स के तहत काम करे।

+0

यह इस सवाल का डुप्लिकेट है: http://stackoverflow.com/questions/17140/how-do-you-spawn-another-process-in-c –

उत्तर

17

आप popen का उपयोग करना चाहते हैं। यह आपको एक यूनिडायरेक्शनल पाइप देता है जिसके साथ आप प्रोग्राम के stdin और stdout तक पहुंच सकते हैं।

popen आधुनिक यूनिक्स और यूनिक्स की तरह ओएस पर मानक है, जिनमें से लिनक्स एक टर्मिनल में एक :-)

प्रकार

man popen 

है इसके बारे में अधिक पढ़ने के लिए।

संपादित

चाहे popen यूनिडायरेक्शनल या द्विदिश पाइप का उत्पादन कार्यान्वयन पर निर्भर करता है। Linux और OpenBSD, popen में यूनिडायरेक्शनल पाइप का उत्पादन होता है, जो केवल पढ़ने या लिखने के लिए ही होते हैं। OS X पर, FreeBSD और NetBSDpopen बिडरेक्शनल पाइप का उत्पादन करता है।

+1

ध्यान दें कि यह stdin _or_ stdout है, दोनों एक साथ नहीं। – wnoise

+0

आधुनिक कार्यान्वयन में, यह stdin और stdout है। पाइप को द्विपक्षीय होने की अनुमति है, हालांकि परंपरागत रूप से यह एकजुट है। उबंटू 9.04 पर – freespace

+0

"मैन पॉपन" कहता है, "चूंकि एक पाइप परिभाषा द्वारा एक-दूसरे के माध्यम से होता है, तो टाइप तर्क केवल पढ़ने या लिखने के लिए निर्दिष्ट नहीं हो सकता है"। – nobar

0

मुझे लगता है कि आप

freopen

इस के लिए

उपयोग कर सकते हैं।

7
  1. pipe(...) के साथ दो पाइप, stdin के लिए एक, stdout के लिए एक बनाएं।
  2. fork(...) प्रक्रिया।
  3. बच्चे की प्रक्रिया में (एक जहां fork(...) रिटर्न 0) dup (...) पाइप stdin/stdout पर पाइप।
  4. exec[v][e] बाल प्रक्रिया में प्रोग्राम फ़ाइल शुरू करने के लिए।
  5. माता-पिता इस प्रक्रिया में (जहां fork) बच्चे की पीआईडी ​​रिटर्न) एक पाश है कि से पढ़ता कर बच्चे की stdout (select(...) या poll(...), read(...)) एक बफर में, जब तक बच्चे समाप्त हो जाता है (waitpid(...))।
  6. अगर यह कुछ उम्मीद करता है तो stdin पर इनपुट के साथ बच्चे को आपूर्ति करें।
  7. जब close(...) पाइप किया गया।
4

मैं नाथन Fellman से असहमत पढ़ें - अन्य प्रश्न हालांकि विषय से संबंधित है, इस का डुप्लिकेट नहीं है।

सरल यूनिडायरेक्शनल संचार के लिए, पॉपन() एक सभ्य समाधान है। हालांकि, यह द्वि-दिशात्मक संचार के लिए कोई उपयोग नहीं है।

आईएमओ, इमोजोर (जॉर्ज फेरेरा) ने द्वि-दिशात्मक संचार के लिए अधिकांश उत्तर (80%?) दिया - लेकिन कुछ महत्वपूर्ण विवरण छोड़ दिए।

  1. यह महत्वपूर्ण है कि माता-पिता प्रक्रिया पाइप के पढ़ने के अंत को बंद कर दें जो कि बच्चे की प्रक्रिया में संदेश भेजने के लिए उपयोग की जाती है।
  2. यह महत्वपूर्ण है कि बाल प्रक्रिया पाइप के लिखने के अंत को बंद करे जिसका उपयोग बाल प्रक्रिया में संदेश भेजने के लिए किया जाता है।
  3. यह महत्वपूर्ण है कि मूल प्रक्रिया पाइप के लिखने के अंत को बंद करे जिसका उपयोग माता-पिता प्रक्रिया को संदेश भेजने के लिए किया जाता है।
  4. यह महत्वपूर्ण है कि बाल प्रक्रिया पाइप के पढ़ने के अंत को बंद करे जिसका उपयोग माता-पिता प्रक्रिया को संदेश भेजने के लिए किया जाता है।

यदि आप पाइप के अप्रयुक्त सिरों को बंद नहीं करते हैं, तो प्रोग्राम समाप्त होने पर आपको समझदार व्यवहार नहीं मिलता है; उदाहरण के लिए, बच्चा अपने मानक इनपुट से पढ़ रहा हो सकता है, लेकिन जब तक कि बच्चे में पाइप का लेखन अंत बंद नहीं होता है, तब तक इसे कभी भी ईओएफ (पढ़ने से शून्य बाइट) नहीं मिलेगा क्योंकि इसमें अभी भी पाइप खुला है और सिस्टम इसे सोचता है कभी-कभी उस पाइप को लिखने के लिए चारों ओर मिल सकता है, भले ही यह वर्तमान में कुछ पढ़ने के लिए इंतजार कर रहा हो।

लेखन प्रक्रियाओं पर विचार करना चाहिए कि सिगिपिप सिग्नल को संभालना है या नहीं, जब आप एक पाइप पर लिखते हैं जहां कोई पठन प्रक्रिया नहीं होती है।

आपको पाइप क्षमता (प्लेटफ़ॉर्म निर्भर, और 4KB जितना छोटा हो सकता है) से अवगत होना चाहिए और कार्यक्रमों को डेडलॉक से बचने के लिए डिज़ाइन करना होगा।

8

मैंने कुछ और समय के लिए कुछ कोड सी कोड लिखा था जो दिखाता है कि यह कैसे करें। यहाँ यह आप के लिए है:

#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 

void error(char *s); 
char *data = "Some input data\n"; 

main() 
{ 
    int in[2], out[2], n, pid; 
    char buf[255]; 

    /* In a pipe, xx[0] is for reading, xx[1] is for writing */ 
    if (pipe(in) < 0) error("pipe in"); 
    if (pipe(out) < 0) error("pipe out"); 

    if ((pid=fork()) == 0) { 
    /* This is the child process */ 

    /* Close stdin, stdout, stderr */ 
    close(0); 
    close(1); 
    close(2); 
    /* make our pipes, our new stdin,stdout and stderr */ 
    dup2(in[0],0); 
    dup2(out[1],1); 
    dup2(out[1],2); 

    /* Close the other ends of the pipes that the parent will use, because if 
    * we leave these open in the child, the child/parent will not get an EOF 
    * when the parent/child closes their end of the pipe. 
    */ 
    close(in[1]); 
    close(out[0]); 

    /* Over-write the child process with the hexdump binary */ 
    execl("/usr/bin/hexdump", "hexdump", "-C", (char *)NULL); 
    error("Could not exec hexdump"); 
    } 

    printf("Spawned 'hexdump -C' as a child process at pid %d\n", pid); 

    /* This is the parent process */ 
    /* Close the pipe ends that the child uses to read from/write to so 
    * the when we close the others, an EOF will be transmitted properly. 
    */ 
    close(in[0]); 
    close(out[1]); 

    printf("<- %s", data); 
    /* Write some data to the childs input */ 
    write(in[1], data, strlen(data)); 

    /* Because of the small amount of data, the child may block unless we 
    * close it's input stream. This sends an EOF to the child on it's 
    * stdin. 
    */ 
    close(in[1]); 

    /* Read back any output */ 
    n = read(out[0], buf, 250); 
    buf[n] = 0; 
    printf("-> %s",buf); 
    exit(0); 
} 

void error(char *s) 
{ 
    perror(s); 
    exit(1); 
} 
संबंधित मुद्दे