Linux shell多管道的C语言实现
时间: 2024-05-05 13:22:08 浏览: 67
在 Linux 中,多管道可以使用 pipe() 系统调用实现,具体实现步骤如下:
1. 创建多个管道
```c
int fd[2][2]; // fd[i][0] 代表第 i 个管道的读端,fd[i][1] 代表第 i 个管道的写端
for (int i = 0; i < n; i++) {
if (pipe(fd[i]) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
}
```
2. fork 出多个子进程,并将它们的标准输入、标准输出连接到管道中
```c
int pid;
for (int i = 0; i < n; i++) {
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) { // 子进程
if (i == 0) { // 第一个子进程
dup2(fd[i][1], STDOUT_FILENO); // 将标准输出连接到 fd[i][1] 上
close(fd[i][0]); // 关闭其它管道
for (int j = 1; j < n; j++) {
close(fd[j][0]);
close(fd[j][1]);
}
} else if (i == n - 1) { // 最后一个子进程
dup2(fd[i-1][0], STDIN_FILENO); // 将标准输入连接到 fd[i-1][0] 上
close(fd[i][0]); // 关闭其它管道
for (int j = 0; j < n - 1; j++) {
close(fd[j][0]);
close(fd[j][1]);
}
} else { // 中间的子进程
dup2(fd[i-1][0], STDIN_FILENO); // 将标准输入连接到 fd[i-1][0] 上
dup2(fd[i][1], STDOUT_FILENO); // 将标准输出连接到 fd[i][1] 上
for (int j = 0; j < n; j++) {
if (j != i - 1 && j != i) {
close(fd[j][0]);
close(fd[j][1]);
}
}
}
execlp(cmd[i][0], cmd[i], NULL); // 执行命令
perror("execlp"); // execlp 函数不返回,如果返回则说明出错了
exit(EXIT_FAILURE);
} else {
// 父进程
if (i == 0) {
close(fd[i][1]); // 关闭写端
} else if (i == n - 1) {
close(fd[i-1][0]); // 关闭读端
} else {
close(fd[i-1][0]);
close(fd[i][1]);
}
}
}
```
3. 等待子进程结束
```c
for (int i = 0; i < n; i++) {
wait(NULL);
}
```
完整的代码实现如下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
char *cmd[3][3] = {
{"ls", "-al", NULL},
{"grep", "test", NULL},
{"wc", "-l", NULL}
};
int n = 3; // 管道数量
int fd[2][2]; // fd[i][0] 代表第 i 个管道的读端,fd[i][1] 代表第 i 个管道的写端
for (int i = 0; i < n; i++) {
if (pipe(fd[i]) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
}
int pid;
for (int i = 0; i < n; i++) {
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
if (i == 0) {
dup2(fd[i][1], STDOUT_FILENO);
close(fd[i][0]);
for (int j = 1; j < n; j++) {
close(fd[j][0]);
close(fd[j][1]);
}
} else if (i == n - 1) {
dup2(fd[i-1][0], STDIN_FILENO);
close(fd[i][0]);
for (int j = 0; j < n - 1; j++) {
close(fd[j][0]);
close(fd[j][1]);
}
} else {
dup2(fd[i-1][0], STDIN_FILENO);
dup2(fd[i][1], STDOUT_FILENO);
for (int j = 0; j < n; j++) {
if (j != i - 1 && j != i) {
close(fd[j][0]);
close(fd[j][1]);
}
}
}
execlp(cmd[i][0], cmd[i], NULL);
perror("execlp");
exit(EXIT_FAILURE);
} else {
if (i == 0) {
close(fd[i][1]);
} else if (i == n - 1) {
close(fd[i-1][0]);
} else {
close(fd[i-1][0]);
close(fd[i][1]);
}
}
}
for (int i = 0; i < n; i++) {
wait(NULL);
}
return 0;
}
```
阅读全文