通过管道使用进程来执行 运行 命令
Using processes to run commands with pipes
我对进程、管道和 dup2 还是个新手,因此我希望有人能帮我弄清楚我创建的程序有什么问题。这个程序应该运行 ls | wc
。到目前为止,我得到的输出是:
wc : standard input : Bad file descriptor
0 0 0
ls : write error : Bad file descriptor
在我得到这个输出后,终端仍然接受输入。就像 wc 仍然是 运行ning,虽然如果我先输入像 ls 这样的命令(之前没有任何其他输入)它 运行s 它们并关闭。我尝试了 运行ning ps before/after 并且程序仍在 运行ning 并且它没有显示任何进程正在打开,除了 bash 和 ps。 (我正在 运行 在 Linux 终端中安装这个程序)
这是我的代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<errno.h>
int main(int argc, char* argv[]){
pid_t pid;
int fd[2];
char com1[1024] = ("ls");
char com2[1024] = ("wc");
pipe(fd);
pid = fork();
if(pid == 0){
open(fd[1]);
dup2(fd[0],STDOUT_FILENO);
close(fd[0]);
execlp(com1, com1, NULL);
}
else {
pid = fork();
if (pid == 0){
open(fd[0]);
dup2(fd[1],STDIN_FILENO);
close(fd[1]);
execlp(com2, com2, NULL);
}
}
return 0;
}
请记住,我知道一些 if 命令需要检查(如 if(pid<0)exit(0);
),但我尽量简化我的代码,以查看是否由于粗心而导致错误。
提前致谢!
pipefd[0]
refers to the read end of the pipe. pipefd[1]
refers to the write end of the pipe.
现在从第一个子进程(调用 ls
命令的进程)中获取这一行:
dup2(fd[0],STDOUT_FILENO);
在这里,您将管道的 read 端复制到 STDOUT_FILENO
,即写入输出的位置。如果您停下来想一想,您将如何写入像 fd[0]
这样的只读文件描述符?
与其他子进程相同,您将管道标准输入的 write 结束。
解决方法很简单:交换您复制的描述符的位置。第一个子进程使用 fd[1]
,第二个子进程使用 fd[0]
。
在您调用 ls
命令的第一个进程中:
dup2(fd[1],STDOUT_FILENO);
close(fd[1]);
execlp(com1, com1, NULL);
并且在您调用 wc
命令的第二个子进程中:
dup2(fd[0],STDIN_FILENO);
close(fd[0]);
execlp(com2, com2, NULL);
我对进程、管道和 dup2 还是个新手,因此我希望有人能帮我弄清楚我创建的程序有什么问题。这个程序应该运行 ls | wc
。到目前为止,我得到的输出是:
wc : standard input : Bad file descriptor
0 0 0
ls : write error : Bad file descriptor
在我得到这个输出后,终端仍然接受输入。就像 wc 仍然是 运行ning,虽然如果我先输入像 ls 这样的命令(之前没有任何其他输入)它 运行s 它们并关闭。我尝试了 运行ning ps before/after 并且程序仍在 运行ning 并且它没有显示任何进程正在打开,除了 bash 和 ps。 (我正在 运行 在 Linux 终端中安装这个程序)
这是我的代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<errno.h>
int main(int argc, char* argv[]){
pid_t pid;
int fd[2];
char com1[1024] = ("ls");
char com2[1024] = ("wc");
pipe(fd);
pid = fork();
if(pid == 0){
open(fd[1]);
dup2(fd[0],STDOUT_FILENO);
close(fd[0]);
execlp(com1, com1, NULL);
}
else {
pid = fork();
if (pid == 0){
open(fd[0]);
dup2(fd[1],STDIN_FILENO);
close(fd[1]);
execlp(com2, com2, NULL);
}
}
return 0;
}
请记住,我知道一些 if 命令需要检查(如 if(pid<0)exit(0);
),但我尽量简化我的代码,以查看是否由于粗心而导致错误。
提前致谢!
pipefd[0]
refers to the read end of the pipe.pipefd[1]
refers to the write end of the pipe.
现在从第一个子进程(调用 ls
命令的进程)中获取这一行:
dup2(fd[0],STDOUT_FILENO);
在这里,您将管道的 read 端复制到 STDOUT_FILENO
,即写入输出的位置。如果您停下来想一想,您将如何写入像 fd[0]
这样的只读文件描述符?
与其他子进程相同,您将管道标准输入的 write 结束。
解决方法很简单:交换您复制的描述符的位置。第一个子进程使用 fd[1]
,第二个子进程使用 fd[0]
。
在您调用 ls
命令的第一个进程中:
dup2(fd[1],STDOUT_FILENO);
close(fd[1]);
execlp(com1, com1, NULL);
并且在您调用 wc
命令的第二个子进程中:
dup2(fd[0],STDIN_FILENO);
close(fd[0]);
execlp(com2, com2, NULL);