2011-02-12 32 views
5
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

int 
main(int argc, char **argv) 
{ 
    int pfds[ 2], i; 
    size_t pbytrd; 
    pid_t childpid; 
    char buffer[ 200]; 

    pipe(pfds); 
    if((childpid = fork()) == -1) 
    { 
      perror("fork error: "); 
      exit(1); 
    } 
    else if(childpid == 0) 
    { 
      close(pfds[ 0]); 
      dup2(pfds[1], 1); 
      close(pfds[ 1]); 
      for(i = 0; i < 10; i++) 
       printf("Hello..."); 
      execlp("xterm","xterm","-e","./sample_a", (char *) 0); 
      exit(0); 
} 
else 
{ 

     close(pfds[ 1]); 
     for(; ;) 
     { 
      if((pbytrd = read(pfds[ 0], buffer, sizeof(buffer))) == -1) 
      { 
       perror(" read error: "); 
       exit(1); 
      } 
      else if(pbytrd == 0) 
      { 

       write(fileno(stdout), "Cannot read from pipe...\n", strlen("Cannot read from pipe...\n")); 
       exit(0); 
      } 
      else 
      { 
       write(fileno(stdout), "MESSAGE: ", strlen("MESSAGE: ")); 
       write(fileno(stdout), buffer, pbytrd); 
      } 
     }  
} 
return(0); 

}dup2() और कार्यकारी()

मेरे sample_a.c कोड के नीचे है:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

int 
main(int argc, char **argv) 
{ 
     int i; 
     for(i= 0; i< 10; i++) 
     write(fileno(stdout), "Hello...", strlen("Hello...")); 
    return(0); 
} 

उपरोक्त कोड में, क्या मैं सच में करना चाहते हैं: 1) पुनर्निर्देशन बाल प्रक्रिया से पाइप तक उत्पादन और माता-पिता को पाइप से पढ़ा जाता है और इसे stdout पर प्रिंट करता है।

मैं stdout से पाइप तक बाल प्रक्रिया आउटपुट ("printf") को पुनर्निर्देशित करने में सक्षम हूं लेकिन मैं execlp की बाल प्रक्रिया, xterm, आउटपुट को पाइप पर रीडायरेक्ट करने में सक्षम नहीं हूं।

क्या कोई मेरी मदद कर सकता है?

उत्तर

4

xterm टर्मिनल एमुलेटर है। यह आपके द्वारा प्रदान किए गए कार्यक्रम को निष्पादित करता है (sample_a), अपने इनपुट और आउटपुट को स्वयं से जोड़ता है, ताकि प्रोग्राम उपयोगकर्ता इनपुट को अपने मानक इनपुट में प्राप्त कर सके, और जो भी वह अपने मानक और त्रुटि आउटपुट को भेजता है उसे प्रिंट करता है।

आपका प्रोग्राम क्या कर रहा है xterm आउटपुट को पाइप से कनेक्ट करने और इसे पढ़ने की कोशिश कर रहा है। लेकिन xterm एक जीयूआई प्रोग्राम है, यह आमतौर पर अपने आउटपुट में डेटा नहीं लिखता है। शायद यह वास्तव में स्पष्ट नहीं है कि आप वास्तव में क्या हासिल करने की कोशिश कर रहे हैं।

यदि आप xterm भाग को हटाते हैं, तो यह काम करना चाहिए जैसा कि आप उम्मीद करते हैं, यानी, मूल प्रक्रिया देखेंगे कि sample_a आउटपुट को क्या लिखता है।

 execlp("./sample_a", "./sample_a", (char *) 0); 
+0

से सहमत हैं, मैं सहमत हूं, अगर मैं xterm भाग को हटा दूंगा तो यह काम करेगा। यह एक प्रोग्रामिंग प्रश्न है जिसे मैंने विश्वविद्यालय की वेबसाइट पर देखा था। व्यायाम xterm विंडो पर उपयोगकर्ता से इनपुट स्वीकार करता है और xterm पर आउटपुट प्रदर्शित करता है लेकिन टर्मिनल विंडो पर किसी भी त्रुटि (पेरर) को मुद्रित किया जाना चाहिए जहां से इसे कहा जाता है। तो क्या कोई रास्ता नहीं है xterm टर्मिनल विंडो पर वापस संवाद कर सकता है? असल में यह बड़ी समस्या का एक छोटा सा हिस्सा है (5-6 पेज समस्या)। उम्मीद है की यह मदद करेगा –

1

xterm में कोई आउटपुट नहीं है, इसलिए इसे कहीं भी रीडायरेक्ट करने का कोई तरीका नहीं है। xterm एक बच्चे को चलाता है और बच्चे के आउटपुट को अपने आप रीडायरेक्ट करता है, इसलिए यदि आप xterm के अलावा कहीं और बच्चे के आउटपुट को रीडायरेक्ट करना चाहते हैं, तो आपको xterm शुरू होने के बाद इसे स्वयं बच्चे में करना होगा। ऐसा करने का सबसे आसान तरीका संभव है कि xterm एक खोल शुरू करें और खोल पुनर्निर्देशन का उपयोग करें।

execlp("xterm", "xterm", "-e", "/bin/sh", "-c", "./sample_a 2>somewhere", 0); 

कुछ उचित साथ somewhere की जगह: बच्चे के लिए सिर्फ stderr अनुप्रेषित करने के लिए, आप की तरह कुछ का उपयोग करेंगे। मान लीजिए कि आप इसे अपने मूल कार्यक्रम में कैप्चर करना चाहते हैं, तो शायद आप tempnam (3) और mkfifo (3) के साथ एक अस्थायी फीफो बनाना चाहते हैं और इसे अपने माता-पिता में पढ़ने के लिए खोलना चाहते हैं। फोर्किंग के बाद इसे बनाने और इसे खोलने से पहले इसे बनाने की ज़रूरत है, क्योंकि खुली इच्छा तब तक अवरुद्ध हो जाएगी जब तक कि खोल चलता है और लिखने के अंत को खोलता है। एक बार खुला होने के बाद, आप फीफो को हटा सकते हैं, और अब अज्ञात फीफो से पढ़ सकते हैं।

1

मुझे एक समान स्थिति का सामना करना पड़ा। मेरा लक्ष्य इसलिए बाल प्रक्रिया से कुछ जानकारी भेजना था जो xterm में चलता है। जैसा कि पहले भी बताया गया था, मैं dup2 का उपयोग करने में सक्षम नहीं था। इसके लिए एक वर्कअराउंड एफडी को नई बाइनरी में xterm args के रूप में पास करना है।

एक सुझाव दिया दृष्टिकोण (संक्षिप्तता के लिए त्रुटि जाँच के बिना) है

if (childpid == 0) 
{ 
    /* child closes read*/ 
    close(pipeFD[0]); 
    char writeFD[10]; // do consider space for '\0' 
    /* Extract the write fd and put it in a char buffer 
     make compatible as per execlp args */ 
    sprintf(writeFD, "%d", pipeFD[1]); 
    /* just pass the writeFD as an arg */ 
    execlp("xterm", "xterm", "-e", "./binary", writeFD, (char *) 0)) 

} 
else 
{ 
    /* parent closes write */ 
    close(pipeFD[1]); 
    if((bytesRead = read(pipeFD[0], buf, SIZE)) != -1) 
    { 
     printf("Recieved %s\n", buf); 
     close(pipeFD[0]); 
    } 
} 

बच्चे प्रक्रिया है कि टर्म में चलता है पर, fd

main(int argc, char** argv) { 
    int fd = atoi(argv[1]); 
    write(fd, buf,sizeof(buf)); 
}  

मैं क्यों dup2 खुराक 'पता नहीं है निकालने xterm के साथ काम नहीं करते हैं, लेकिन यह कामकाज आवश्यकता हल करता है।

1

पाइपएफडी सरणी एक बार xterm विंडो बनाने के बाद, अंदर और बाहर दो फ़ाइल विवरण संग्रहीत करता है।बच्चे की प्रक्रिया को नहीं पता कि कहां लिखना है। तो आप dup2:

dup2(pipeFD[1],100); 
close(pipeFD[1]); 

यह पुराने पोर्ट को पुराने पोर्ट (अन्य नंबरों पर भी काम करता है) पर नक्शा दिखाता है। और xterm में आप पाइप को

write(100,"something you wanna to write").