我试图在C中实现一个shell。我可以使用简单的execvp()执行简单的命令,但是其中一个要求是管理像这样的命令:“ls -l | head | tail -4” ‘循环,只有一个’pipe()’语句重定向stdin和stdout。几天后,我有点迷失了。
N =简单命令数(示例中为3:ls,head,tail)
命令=具有命令的结构体列表,如下所示:
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
所以,我做了for循环,并开始重定向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]); } }
我想要创建的是一个“进程”的子进程:
[ls -l] —-pipe—-> [head] —-pipe—-> [tail -4]
所有这些进程都有一个根(这个进程运行我的shell),所以,第一个父亲也是一个shell进程的一个小孩,我有点疲惫已经有人可以帮助我吗?
我甚至不知道孩子是否应该是执行命令的人。
多谢你们 !!
没有什么复杂的,只要记住,最后一个命令应该输出到原始进程的文件描述符1,第一个应该从原始进程文件描述符0读取。你只是按顺序产生进程,沿着输入端以前的管道呼叫。
所以,这里有以下类型:
#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); }
出现工作:)