2011-11-11 16 views
6

में लिखें मैं एक विशिष्ट मानक इनपुट के साथ एक प्रोग्राम चलाने की कोशिश कर रहा हूं। मैं एक फ़ाइल की एक फ़ाइल वर्णनकर्ता का उपयोग कर जहां मैं क्या stdin में रखना चाहते हैं सफल होने, लेकिन मैं stdin पर सीधे लिखने के लिए असफल:execv * और stdin

$cat input.test 
echo Hello 
$ 

कोड सी:

int main(int argc, char **argv) 
{ 
    int fd = 0; 

    fd = open("input.test", O_CREAT); 
    close(STDIN_FILENO); 
    dup2(fd, STDIN_FILENO); 
    char *const args[] = { "bash", NULL }; 
    execvp("bash", args); 
} 

कि काम करता है:

$./a.out 
Hello 
$ 

लेकिन अगर मैं और पाइप कुछ भी नहीं कार्यक्रम प्रदर्शित करता है का उपयोग कर STDIN पर सीधे लिखने की कोशिश रहती है चल रहा है:

int main(int argc, char **argv) 
{ 
    int fds[2]; 

    pipe(fds); 
    close(STDIN_FILENO); 
    dup2(fds[1], STDIN_FILENO); 
    write(fds[1], "echo Hello;", 11); // Résults are identics with fds[0] 
    char *const args[] = { "bash", NULL }; 
    execvp("bash", args); 
} 

आपकी मदद

Cordially, Bastien के लिए धन्यवाद।

संपादित समस्या हल: अपने जवाब के लिए

धन्यवाद, यहाँ कोड काम करता है जो:

int main(void) 
{ 
    int fd[2]; 
    pid_t pid; 

    if (pipe(fd) < 0) 
     return EXIT_FAILURE; 

    if ((pid = fork()) < 0) 
     return EXIT_FAILURE; 
    else if (pid != 0) { /* father */ 
     close(fd[1]); 
     dup2(fd[0], STDIN_FILENO); 
     execlp("bash", "bash", (char *)0); 
    } else { /* son */ 
     close(fd[0]); 
     write(fd[1], "echo hello\n", 11); 
    } 

    return EXIT_SUCCESS; 
} 

उत्तर

4

आपको पाइप के पढ़ने की ओर stdin पर लिखने की आवश्यकता नहीं है, लिखने की तरफ। (और लिखने ओर करने के लिए लिखते हैं, जाहिर है।)

#include <unistd.h> 
#include <string.h> 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
    int fds[2]; 
    char cmd[] = "echo hello\nexit\n"; 

    pipe(fds); 
    close(STDIN_FILENO); 
    dup2(fds[0], STDIN_FILENO); 
    write(fds[1], cmd, strlen(cmd)); 
    char *const args[] = { "bash", NULL }; 
    execvp("bash", args); 
    return 0; 
} 

आप उन सभी कार्यों की वापसी मूल्यों की जाँच हालांकि सुनिश्चित करें, आप अगर तुम नहीं अपने कोड डिबग करने के लिए प्रबंधन नहीं करेंगे।

+0

आप दूसरों को क्यों कम कर रहे हैं?पूछताछ दिमाग जानना चाहते हैं :) – Will

+0

मुझे नहीं पता कि सभी उत्तरों को क्यों हटा दिया गया था। – Mat

2

जब आप पाइप फोन, एफडी [0] पढ़ने के लिए खुला है, और fd [1] है लेखन के लिए खुला है। आपको पढ़ने वाले पक्ष (एफडी [0]) पर stdin डुप्लिकेट करना चाहिए और लिखने की ओर लिखना चाहिए (एफडी [1])। लिखने के वापसी मूल्य की जांच करें: यह शायद -1 है।

लेकिन एक बड़ा मुद्दा है। आप कभी भी पाइप के दोनों तरफ बंद नहीं करते हैं। बैश एक पठन पर अवरुद्ध हो सकता है और पाइप के लिखने की तरफ बंद होने तक कुछ भी नहीं कर सकता। डुप्ली और लिखने के बाद आपको पाइप के दोनों तरफ बंद करना चाहिए। (या FD_CLOEXEC सेट करें)।

3

execv और मित्र वर्तमान चल रहे प्रोग्राम को निर्दिष्ट एक के साथ प्रतिस्थापित करते हैं; वे वापस नहीं आते - निष्पादन इसके बजाय नए कार्यक्रम की शुरुआत में जारी है।

तो आप सामान्य रूप से क्या करते हैं fork और, कांटे में से एक में, execv पर कॉल करें। फिर आप अन्य फोर्क में जारी अपने प्रोग्राम से पाइप के माध्यम से पढ़ते और लिखते हैं। ज्यादातर भाषाओं में ऐसा करने के लिए आमतौर पर popen फ़ंक्शन होते हैं; दुख की बात है कि पॉज़िक्स में पॉपन() सख्ती से पढ़ा या लिखना और बोली लगाने वाला नहीं है।

सौभाग्य से, मेरे पास made, tested and publishedpopen3 फ़ंक्शन है। यह आपको तीन फाइल डिस्क्रिप्टर वापस देता है - एक प्रक्रिया के लिए stdin के लिए, और दो stdout और stderr के लिए। फिर आप stdin पर लिख() का उपयोग कर सकते हैं।

0

यह भी ध्यान दें कि ऐसा करने के तरीके से आप पाइप बफर आकार पर निर्भर हैं। यदि आप बहुत अधिक लिखते हैं, तो लिखने को अवरुद्ध कर दिया जाएगा क्योंकि कोई पाठक नहीं है। इसे भरोसेमंद करें, आपको फोर्क() करना चाहिए, बच्चे में निष्पादन करना चाहिए और माता-पिता में पाइप को लिखना चाहिए। इस तरह पाइप में एक पाठक होगा और आप जितना डेटा चाहते हैं उतना डेटा लिखने में सक्षम होंगे।