दिलचस्प पोस्ट
जावास्क्रिप्ट के साथ एक HTML सूची को सॉर्ट करें मैक्रोज़ के लिए मुझे दुराचार की दोहरी परत की आवश्यकता क्यों है? JQuery के साथ पृष्ठ स्क्रॉलिंग को प्रोग्रामेटिक रूप से अक्षम कैसे करें एक अन्य UIView के तहत एक UIView के साथ संपर्क की अनुमति अमृत ​​सूची में चार सूचियों के रूप में व्याख्या की गई है TypeError: बाध्यकारी onClick पर अव्यवस्था <function_name> की अपरिभाषित नहीं पढ़ सकता है पासवर्ड मास्किंग कंसोल अनुप्रयोग जावा – नियमित अभिव्यक्ति कोड में टिप्पणियां ढूंढने Angularjs में एंकर लिंक? com.jcraft.jsch.JSchException: अज्ञातहॉस्टकी स्ट्रिंग के लिए तत्काल प्रारूप करें इफ्रेम कॉल को कैसे ब्लॉक करें सीएसएस का उपयोग कर एक लिंक डालें क्या int – int (int) X 'को अंतराल और कास्टिंग के बीच कोई विशेष अंतर है? php मेल के लिए smtp कॉन्फ़िगरेशन

शेल में पाइप के साथ n आज्ञाओं को कनेक्ट करना?

मैं सी में एक खोल को लाू करने की कोशिश कर रहा हूं। मैं सरल आदेशों को सरल execvp () के साथ ठीक ठीक कर सकता हूं लेकिन एक आवश्यकताएं इस तरह से कमांड का प्रबंधन करना है: "ls -l | head | tail -4" के साथ 'के लिए 'पाश और केवल एक' पाइप () 'स्टेटमेंट को पुनर्निर्देशित करना stdin और stdout अब दिनों के बाद मैं थोड़ा खो गया हूँ।

N = सरल कमांडों की संख्या (उदाहरण में 3: एलएस, सिर, पूंछ) कमांड = कमांडों के साथ स्ट्रैक्ट्स की एक सूची, जैसे:

commands[0].argv[0]: ls commands[0].argv[1]: -l commands[1].argv[0]: head commands[2].argv[0]: tail commands[2].argv[1]: -4 

इसलिए, मैंने पाश के लिए सभी आदेशों को जोड़ने के लिए, पाश के लिए, और stdin और stdout को पुनर्निदेशित करने के लिए शुरू किया, लेकिन … मुझे यह पता नहीं है कि यह काम क्यों नहीं करता।

 for (i=0; i < n; i++){ pipe(pipe); if(fork()==0){ // CHILD close(pipe[0]); close(1); dup(pipe[1]); close(pipe[1]); execvp(commands[i].argv[0], &commands[i].argv[0]); perror("ERROR: "); exit(-1); }else{ // FATHER close(pipe[1]); close(0); dup(pipe[0]); close(pipe[0]); } } 

मैं क्या बनाना चाहता हूँ यह एक चालाकी प्रक्रिया का 'लाइन' है:

[एलएस-एल] —- पाइप —-> [सिर] —- पाइप —-> [पूंछ -4]

इस सभी प्रक्रियाओं में एक जड़ है (मेरे खोल को चलाने की प्रक्रिया), पहले पिता भी शेल प्रक्रिया का बच्चा है, मैं पहले से थक चुका हूं, कोई मुझे यहाँ मदद कर सकता है?

मुझे यह भी भरोसा नहीं है कि यदि बच्चे आज्ञाओं को क्रियान्वित करने वाले हों।

धन्यवाद दोस्तों !!

वेब के समाधान से एकत्रित समाधान "शेल में पाइप के साथ n आज्ञाओं को कनेक्ट करना?"

यहां कुछ भी जटिल नहीं है, बस इस बात को ध्यान में रखिए कि आखिरी कमांड मूल प्रक्रिया 'फ़ाइल डिस्क्रिप्टर 1 में आउटपुट होनी चाहिए और पहले को मूल प्रक्रिया फ़ाइल डिस्क्रिप्टर 0 से पढ़ना चाहिए। आप केवल प्रक्रियाओं को क्रम में अंडे में लेते हैं, साथ में इनपुट पक्ष के साथ ले जाते हैं प्रीओइज़ pipe कॉल

तो, ये प्रकार हैं:

 #include <unistd.h> struct command { const char **argv; }; 

सरल अच्छी तरह से परिभाषित शब्दों के साथ एक सहायक कार्य करें:

 int spawn_proc (int in, int out, struct command *cmd) { pid_t pid; if ((pid = fork ()) == 0) { if (in != 0) { dup2 (in, 0); close (in); } if (out != 1) { dup2 (out, 1); close (out); } return execvp (cmd->argv [0], (char * const *)cmd->argv); } return pid; } 

और यहां मुख्य कांटा दिनचर्या है:

 int fork_pipes (int n, struct command *cmd) { int i; pid_t pid; int in, fd [2]; /* The first process should get its input from the original file descriptor 0. */ in = 0; /* Note the loop bound, we spawn here all, but the last stage of the pipeline. */ for (i = 0; i < n - 1; ++i) { pipe (fd); /* f [1] is the write end of the pipe, we carry `in` from the prev iteration. */ spawn_proc (in, fd [1], cmd + i); /* No need for the write end of the pipe, the child will write here. */ close (fd [1]); /* Keep the read end of the pipe, the next child will read from there. */ in = fd [0]; } /* Last stage of the pipeline - set stdin be the read end of the previous pipe and output to the original file descriptor 1. */ if (in != 0) dup2 (in, 0); /* Execute the last stage with the current process. */ return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv); } 

और एक छोटी सी परीक्षा:

 int main () { const char *ls[] = { "ls", "-l", 0 }; const char *awk[] = { "awk", "{print $1}", 0 }; const char *sort[] = { "sort", 0 }; const char *uniq[] = { "uniq", 0 }; struct command cmd [] = { {ls}, {awk}, {sort}, {uniq} }; return fork_pipes (4, cmd); } 

काम करने के लिए दिखाई देता है 🙂

सबसे पहले, आप समय से पहले पाइप बंद कर रहे हैं। केवल उस अंत को बंद करें जो आपको वर्तमान प्रक्रिया में नहीं चाहिए, और बच्चे में stdin / stdout को बंद करने के लिए याद रखें।

दूसरे, आपको पिछली कमांड से एफडी को याद रखना होगा। इसलिए, दो प्रक्रियाओं के लिए, यह दिखता है:

 int pipe[2]; pipe(pipe); if ( fork() == 0 ) { /* Redirect output of process into pipe */ close(stdout); close(pipe[0]); dup2( pipe[1], stdout ); execvp(commands[0].argv[0], &commands[0].argv[0]); } if ( fork() == 0 ) { /* Redirect input of process out of pipe */ close(stdin); close(pipe[1]); dup2( pipe[0], stdin ); execvp(commands[1].argv[0], &commands[1].argv[0]); } /* Main process */ close( pipe[0] ); close( pipe[1] ); waitpid(); 

अब आपकी नौकरी इस पर त्रुटि से निपटने को जोड़ना है और शुरू करने के लिए एन प्रक्रियाओं के लिए एन -1 पाइप उत्पन्न करती है। पहले कांटा () खंड में कोड प्रक्रियाओं 1..n-1 के लिए उपयुक्त पाइप, और प्रक्रियाओं के लिए दूसरे कांटा () ब्लॉक में कोड चलाने की जरूरत है 2.. एन