我正努力为类实现一个具有管道的shell。读取C块上的UNIX管道
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
相同。例如:
$ 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,它会做很多事情:
for (cmdi = 0; cmds[cmdi].cmd != NULL; cmdi++) {
process_command(&cmds[cmdi]);
}
现在,里面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
可能是什么问题呢?
哼,不起作用:\它仍然是相同的,除了标准输入/标准输出关闭运行命令之前,所以例如'猫'失败与'猫:stdin:错误的文件描述符。但即使我避免关闭stdin/out,其行为与以前相同。 据我所知,'cmd - >(in | out)[(0 | 1)]'指的是与'fileno(std(in | out)'相同的底层文件,不是吗? –
,每个管道都有一个读描述符和一个写描述符,据我所知,父和子之间(或两个子之间)有两个管道。在每个子进程中,你只需要在'stdin'上打开一个管道读端的'dup2()',并在'stdout'上打开另一个管道写端的'dup2()';应该关闭管道的所有四个末端(这是人们的惊喜)。我不确定是否有足够的代码来说明还有什么问题。 –
谢谢乔纳森,我没有像你说的那样关闭父母管道的两端。非常感谢! –