मैं कक्षा के लिए पाइपलाइनों के साथ एक खोल लागू करने के लिए संघर्ष कर रहा हूं। पाइप लाइन मेंसी ब्लॉक पर यूनिक्स पाइप पढ़ने पर
typedef struct {
char** cmd;
int in[2];
int out[2];
} cmdio;
cmdio cmds[MAX_PIPE + 1];
आदेश पढ़ सकते हैं और cmds
में संग्रहीत हैं।
cmdio[i].in
इनपुट पाइप के फ़ाइल डिस्क्रिप्टर की जोड़ी pipe()
द्वारा लौटा दी गई है। पहले कमांड के लिए, जो टर्मिनल इनपुट से पढ़ता है, यह सिर्फ {fileno (stdin), -1} है। cmdin[i].out
आउटपुट पाइप/टर्मिनल आउटपुट के लिए समान है। cmdio[i].in
cmd[i-1].out
जैसा ही है। उदाहरण के लिए: process_command अंदर अब
for (cmdi = 0; cmds[cmdi].cmd != NULL; cmdi++) {
process_command(&cmds[cmdi]);
}
,:
$ ls -l | sort | wc
CMD: ls -l
IN: 0 -1
OUT: 3 4
CMD: sort
IN: 3 4
OUT: 5 6
CMD: wc
IN: 5 6
OUT: -1 1
हम process_command करने के लिए प्रत्येक आदेश है, जो चीजों के एक नंबर करता है पारित
if (!(pid_fork = fork())) {
dup2(cmd->in[0], fileno(stdin));
dup2(cmd->out[1], fileno(stdout));
if (cmd->in[1] >= 0) {
if (close(cmd->in[1])) {
perror(NULL);
}
}
if (cmd->out[0] >= 0) {
if (close(cmd->out[0])) {
perror(NULL);
}
}
execvp(cmd->cmd[0], cmd->cmd);
exit(-1);
}
समस्या से पढ़ कि है पाइप ब्लॉक हमेशा के लिए:
COMMAND $ ls | wc
Created pipe, in: 5 out: 6
Foreground pid: 9042, command: ls, Exited, info: 0
[blocked running read() within wc]
हैं, तो execvp
साथ प्रक्रिया का आदान प्रदान करने के बजाय, मैं सिर्फ ऐसा करते हैं:
if (!(pid_fork = fork())) {
dup2(cmd->in[0], fileno(stdin));
dup2(cmd->out[1], fileno(stdout));
if (cmd->in[1] >= 0) {
if (close(cmd->in[1])) {
perror(NULL);
}
}
if (cmd->out[0] >= 0) {
if (close(cmd->out[0])) {
perror(NULL);
}
}
char buf[6];
read(fileno(stdin), buf, 5);
buf[5] = '\0';
printf("%s\n", buf);
exit(0);
}
यह काम करने के लिए होता है:
COMMAND $ cmd1 | cmd2 | cmd3 | cmd4 | cmd5
Pipe creada, in: 11 out: 12
Pipe creada, in: 13 out: 14
Pipe creada, in: 15 out: 16
Pipe creada, in: 17 out: 18
hola!
Foreground pid: 9251, command: cmd1, Exited, info: 0
Foreground pid: 9252, command: cmd2, Exited, info: 0
Foreground pid: 9253, command: cmd3, Exited, info: 0
Foreground pid: 9254, command: cmd4, Exited, info: 0
hola!
Foreground pid: 9255, command: cmd5, Exited, info: 0
क्या हो सकता है समस्या?
हम, काम नहीं करते हैं: \ यह अभी भी वही है, सिडिन/stdout को कमांड चलाने से पहले बंद हो जाता है, उदाहरण के लिए 'cat' 'cat: stdin: खराब फ़ाइल वर्णनकर्ता' के साथ विफल रहता है। लेकिन अगर मैं stdin/बाहर व्यवहार से बचने से बचने के लिए पहले जैसा ही है। जहां तक मैं 'cmd -> (in | out) दोनों को समझता हूं [(0 | 1)]' उसी अंतर्निहित फ़ाइलों को 'fileno (std (in | out)' के रूप में संदर्भित करें, है ना? –
खैर , प्रत्येक पाइप में एक पठन वर्णनकर्ता और एक लेखन वर्णनकर्ता होता है। जैसा कि मैं इसे समझता हूं, आपके पास माता-पिता और बच्चे (या दो बच्चों के बीच) के बीच दो पाइप हैं।प्रत्येक बच्चे की प्रक्रिया में, आप 'stdin' पर खुले एक पाइप के पढ़ने के अंत में केवल' dup2() 'और' stdout' पर खुले अन्य पाइप के लिखने के अंत के 'dup2()' चाहते हैं; पाइप के सभी मूल सिरों को बंद किया जाना चाहिए (जो लोगों को आश्चर्यचकित करता है)। मुझे यकीन नहीं है कि हमारे पास यह बताने के लिए पर्याप्त कोड है कि और क्या गलत हो रहा है। –
धन्यवाद जोनाथन, मैं आपके जैसे माता-पिता से पाइप के दोनों सिरों को बंद नहीं कर रहा था। आपका बहुत बहुत धन्यवाद! –