Linux 进程间通信 管道系列: 匿名和命名管道,自定义shell当中命令行管道的模拟实现
在Linux中,命令行管道(|
)是通过使用匿名管道(pipe()
)或命名管道(FIFO)实现的。以下是一个简单的自定义shell,它模拟了命令行管道的功能:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_LINE 80
int main() {
int fd[2];
pid_t pid;
char line[MAX_LINE];
int n, i;
while (1) {
// 打印提示符
printf("myshell> ");
fflush(stdout);
// 读取用户输入,以空格分隔命令
char* args[MAX_LINE/2+1]; // 假设每个命令行不超过80/2
int arg_count = 0;
char* token = strtok(gets(line), " ");
while (token != NULL) {
args[arg_count++] = token;
token = strtok(NULL, " ");
}
args[arg_count] = NULL; // 结尾添加NULL
// 创建管道
if (pipe(fd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
// 子进程执行命令
if (pid == 0) {
close(fd[1]); // 子进程关闭写端
dup2(fd[0], STDIN_FILENO); // 将管道读端 dup 到标准输入
close(fd[0]);
// 执行下一个命令,如果有的话
if (arg_count > 1 && strcmp(args[arg_count-1], "|") != 0) {
if (execlp(args[arg_count], NULL) == -1) {
perror("execlp");
exit(EXIT_FAILURE);
}
}
_exit(EXIT_SUCCESS); // 如果没有下一个命令,则子进程结束
} else {
close(fd[0]); // 父进程关闭读端
// 如果存在下一个命令,继续创建子进程执行该命令
if (arg_count > 1 && strcmp(args[arg_count-1], "|") == 0) {
if (pipe(fd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
// 子进程执行命令
if (pid == 0) {
close(fd[1]); // 子进程关闭写端
dup2(fd[0], STDIN_FILENO); // 将管道读端 dup 到标准输入
close(fd[0]);
// 执行最后一个命令
if (execlp(args[arg_count-2], NULL) == -1) {
perror("execlp");
exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS); // 子进程结束
评论已关闭