使用 2 个管道执行 cat|grep|grep
Executing cat|grep|grep using 2 pipes
标题是 self-explanatory 我想做的事情,这是我当前的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
pid_t pid ;
int fd[2], fd2[2];
pipe(fd);
pipe(fd2);
pid = fork();
if(pid == 0) {
close(1);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
char *exp[] = {"cat", "filename.txt", NULL};
execvp("cat", exp);
exit(EXIT_FAILURE);
}
else if(pid > 0) {
close(1);
dup(fd2[1]);
close(fd2[0]);
close(fd2[1]);
char *exp[] = {"grep", "-w", "stringname", NULL};
execvp(exp[0], exp);
pid_t pid2=fork();
close(0);
dup(fd[0]);
close (fd[1]);
close(fd[0]);
char *exp2[] = {"grep", "-c", "stringname", NULL};
execvp(exp2[0], exp2);
exit(EXIT_FAILURE);
}
else {
printf("Error in forking");
exit(EXIT_FAILURE);
}
close(fd[0]);
close(fd[1]);
close(fd2[0]);
close(fd2[1]);
return 0;
}
目前程序正在编译但没有执行(它在执行时卡在某个地方,我没有得到任何输出),关于我做错了什么以及如何修复它的任何帮助?
您的代码中存在一些问题:
execvp(exp[0], exp);
在第一个 grep 之后将在第二个 fork()
之前执行。这是一个逻辑错误。
- 我不太明白你是如何使用管道的文件描述符的。您应该将 stdin 和 stdout 替换为管道的适当末端并关闭所有其他末端。
我用这些更改重写了您的代码,使用 dup2 使其更清晰:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
int pipes[4];
// Create two pipes
pipe(pipes);
pipe(pipes + 2);
// Execute cat
if (fork() == 0) {
// Replace output with write end of first pipe
dup2(pipes[1], 1);
// Close all ends of pipes (we already copied it with `dup2`)
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
char *exp[] = {"cat", "filename.txt", NULL};
execvp(exp[0], exp);
perror("cat failed");
exit(EXIT_FAILURE);
} else {
// Execute first grep
if (fork() == 0) {
// Replace input with read end of 1st pipe
dup2(pipes[0], 0);
// Replace output with write end of 2nd pipe
dup2(pipes[3], 1);
// Close all ends of pipes
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
char *exp[] = {"grep", "-w", "stringname", NULL};
execvp(exp[0], exp);
perror("first grep failed");
exit(EXIT_FAILURE);
} else {
// Execute second grep
if (fork() == 0) {
// Replace input with read end of 2nd pipe
dup2(pipes[2], 0);
// Close all ends of pipes
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
char *exp[] = {"grep", "-c", "stringname", NULL};
execvp(exp[0], exp);
perror("second grep failed");
exit(EXIT_FAILURE);
}
}
}
// Close all ends of pipes
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
for (int i = 0; i < 3; i++) {
wait(NULL);
}
return 0;
}
标题是 self-explanatory 我想做的事情,这是我当前的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
pid_t pid ;
int fd[2], fd2[2];
pipe(fd);
pipe(fd2);
pid = fork();
if(pid == 0) {
close(1);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
char *exp[] = {"cat", "filename.txt", NULL};
execvp("cat", exp);
exit(EXIT_FAILURE);
}
else if(pid > 0) {
close(1);
dup(fd2[1]);
close(fd2[0]);
close(fd2[1]);
char *exp[] = {"grep", "-w", "stringname", NULL};
execvp(exp[0], exp);
pid_t pid2=fork();
close(0);
dup(fd[0]);
close (fd[1]);
close(fd[0]);
char *exp2[] = {"grep", "-c", "stringname", NULL};
execvp(exp2[0], exp2);
exit(EXIT_FAILURE);
}
else {
printf("Error in forking");
exit(EXIT_FAILURE);
}
close(fd[0]);
close(fd[1]);
close(fd2[0]);
close(fd2[1]);
return 0;
}
目前程序正在编译但没有执行(它在执行时卡在某个地方,我没有得到任何输出),关于我做错了什么以及如何修复它的任何帮助?
您的代码中存在一些问题:
execvp(exp[0], exp);
在第一个 grep 之后将在第二个fork()
之前执行。这是一个逻辑错误。- 我不太明白你是如何使用管道的文件描述符的。您应该将 stdin 和 stdout 替换为管道的适当末端并关闭所有其他末端。
我用这些更改重写了您的代码,使用 dup2 使其更清晰:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
int pipes[4];
// Create two pipes
pipe(pipes);
pipe(pipes + 2);
// Execute cat
if (fork() == 0) {
// Replace output with write end of first pipe
dup2(pipes[1], 1);
// Close all ends of pipes (we already copied it with `dup2`)
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
char *exp[] = {"cat", "filename.txt", NULL};
execvp(exp[0], exp);
perror("cat failed");
exit(EXIT_FAILURE);
} else {
// Execute first grep
if (fork() == 0) {
// Replace input with read end of 1st pipe
dup2(pipes[0], 0);
// Replace output with write end of 2nd pipe
dup2(pipes[3], 1);
// Close all ends of pipes
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
char *exp[] = {"grep", "-w", "stringname", NULL};
execvp(exp[0], exp);
perror("first grep failed");
exit(EXIT_FAILURE);
} else {
// Execute second grep
if (fork() == 0) {
// Replace input with read end of 2nd pipe
dup2(pipes[2], 0);
// Close all ends of pipes
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
char *exp[] = {"grep", "-c", "stringname", NULL};
execvp(exp[0], exp);
perror("second grep failed");
exit(EXIT_FAILURE);
}
}
}
// Close all ends of pipes
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
for (int i = 0; i < 3; i++) {
wait(NULL);
}
return 0;
}