如何链接多个管道? (加上奇怪的错误)
How to chain multiple pipes? (plus weird buggs)
我正在尝试编写一个可以处理管道命令的简单 shell。我希望能够处理所有链接在一起的多个管道,但我很难弄清楚如何实现这样的东西。
这是我目前的尝试:
int status;
int lastToken = 0;
int pipe_pid;
//create the pipes
int pipefd[pipes][2];
// Loop to run all commands in the vertical list.
while(1){
if (c->type == TOKEN_PIPE){
// Here is where we deal with pipes
for (int i = 0; i < pipes; i++){
pipe(pipefd[i]);
pipe_pid = fork();
//this is a receiving pipe
if (pipe_pid == 0){
// create the write end of the pipe
dup2(pipefd[i][WRITE_SIDE], STDOUT_FILENO);
close(pipefd[i][READ_SIDE]);
close(pipefd[i][WRITE_SIDE]);
execvp(c->argv[0], c->argv);
// printf("parent pipe\n");
}
//this is a writing pipe
else{
close(pipefd[i][WRITE_SIDE]);
dup2(pipefd[i][READ_SIDE], STDIN_FILENO);
close(pipefd[i][READ_SIDE]);
// printf("child pipe\n");
}
}
// This stuff happens for all commands
lastToken = c->type;
// If it's the last command, we're done
if (c->next == NULL){
break;
}
else{
c = c->next;
}
}
命令在链表中链接在一起,c 是我的命令指针
pipes 是我在解析字符串时创建的一个变量,所以我知道有多少'|'我在命令中看到了。这应该告诉我需要分叉的子进程数。
我使用管道为管道描述符创建一个二维数组。
然后我想遍历管道并为每个管道分叉一次,并使用 dup2 映射输入和输出。
我遇到了我无法弄清楚的不一致错误。首先,每次我 运行 管道命令时,我的 shell 立即崩溃,没有段错误或其他打印错误。
其次,如果我 运行 命令如 echo foo | wc -c
我有时会得到 4 有时会得到 0 作为输出。
我确定我只是在做一些愚蠢的事情,但我不确定是什么:/
我发现我做错了什么,我在所有线程使用完管道之前就关闭了管道。我通过关闭关闭调用来修复它。
// writing side of the pipe
if (c->type == TOKEN_PIPE){
close(c->pipefd[READ_SIDE]);
dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
}
// receiving side of the pipe
if (commandPrev->type == TOKEN_PIPE){
close(commandPrev->pipefd[WRITE_SIDE]);
dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
}
然后在父线程中,就在我重复我的僵尸之前,我检查已完成使用的管道并关闭它们。
// writing side of the pipe
if (c->type == TOKEN_PIPE){
close(c->pipefd[READ_SIDE]);
dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
}
// receiving side of the pipe
if (commandPrev->type == TOKEN_PIPE){
close(commandPrev->pipefd[WRITE_SIDE]);
dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
close(commandPrev->pipefd[READ_SIDE]);
我不确定这是否是最佳方式,但它对我来说没有错误。
我正在尝试编写一个可以处理管道命令的简单 shell。我希望能够处理所有链接在一起的多个管道,但我很难弄清楚如何实现这样的东西。
这是我目前的尝试:
int status;
int lastToken = 0;
int pipe_pid;
//create the pipes
int pipefd[pipes][2];
// Loop to run all commands in the vertical list.
while(1){
if (c->type == TOKEN_PIPE){
// Here is where we deal with pipes
for (int i = 0; i < pipes; i++){
pipe(pipefd[i]);
pipe_pid = fork();
//this is a receiving pipe
if (pipe_pid == 0){
// create the write end of the pipe
dup2(pipefd[i][WRITE_SIDE], STDOUT_FILENO);
close(pipefd[i][READ_SIDE]);
close(pipefd[i][WRITE_SIDE]);
execvp(c->argv[0], c->argv);
// printf("parent pipe\n");
}
//this is a writing pipe
else{
close(pipefd[i][WRITE_SIDE]);
dup2(pipefd[i][READ_SIDE], STDIN_FILENO);
close(pipefd[i][READ_SIDE]);
// printf("child pipe\n");
}
}
// This stuff happens for all commands
lastToken = c->type;
// If it's the last command, we're done
if (c->next == NULL){
break;
}
else{
c = c->next;
}
}
命令在链表中链接在一起,c 是我的命令指针
pipes 是我在解析字符串时创建的一个变量,所以我知道有多少'|'我在命令中看到了。这应该告诉我需要分叉的子进程数。
我使用管道为管道描述符创建一个二维数组。
然后我想遍历管道并为每个管道分叉一次,并使用 dup2 映射输入和输出。
我遇到了我无法弄清楚的不一致错误。首先,每次我 运行 管道命令时,我的 shell 立即崩溃,没有段错误或其他打印错误。
其次,如果我 运行 命令如 echo foo | wc -c
我有时会得到 4 有时会得到 0 作为输出。
我确定我只是在做一些愚蠢的事情,但我不确定是什么:/
我发现我做错了什么,我在所有线程使用完管道之前就关闭了管道。我通过关闭关闭调用来修复它。
// writing side of the pipe
if (c->type == TOKEN_PIPE){
close(c->pipefd[READ_SIDE]);
dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
}
// receiving side of the pipe
if (commandPrev->type == TOKEN_PIPE){
close(commandPrev->pipefd[WRITE_SIDE]);
dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
}
然后在父线程中,就在我重复我的僵尸之前,我检查已完成使用的管道并关闭它们。
// writing side of the pipe
if (c->type == TOKEN_PIPE){
close(c->pipefd[READ_SIDE]);
dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
}
// receiving side of the pipe
if (commandPrev->type == TOKEN_PIPE){
close(commandPrev->pipefd[WRITE_SIDE]);
dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
close(commandPrev->pipefd[READ_SIDE]);
我不确定这是否是最佳方式,但它对我来说没有错误。