date
2022 0601
简介
带管道(简单实现 只支持一个管道)
#测试样例
ls -l | more
ps -ef | wc -l
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
int main(void)
{
char buf[256], *argv[256], **p;
int sv = 0;
//管道参数
char *cmd2, *argv2[256];
int fd[2];
for (;;)
{
printf("=> ");
//读入标准输入
if (fgets(buf, sizeof(buf), stdin) == NULL) exit(0); //ctrl+D退出
//没有管道 退出
if((cmd2 = strstr(buf, "|")) == NULL) exit(0);
//确定第二个命令的起点
*(cmd2++) = '\0';
//对字符串进行分割 结果放到argv里面
for (p = &argv[0], *p = strtok(buf, " \t\n"); *p != NULL;
*++p = strtok(NULL, " \t\n"));
//第二个命令 数组argv2[] 起点 cmd2
for (p = &argv2[0], *p = strtok(cmd2, " \t\n"); *p != NULL;
*++p = strtok(NULL, " \t\n"));
//空输入
if (argv[0] == NULL || argv2[0] == NULL) exit(0);
//创建管道
pipe(fd);
//两个进程分别执行两个cmd(argv[] 和 argv2[])
// int sv1 = fork();
// int sv2 = fork();
if(fork() == 0) {
//用管道写端口 替换 子进程的标准输出, 即子进程输出到写端口
dup2(fd[1], 1);
//这里其实管道还在 只有管道所有写段读端全部关闭 管道才消失 下面同理
close(fd[1]);
close(fd[0]);
execvp(argv[0], argv);
fprintf(stderr, "** bad command 1 : %m\n");
exit(1);
} else if(fork() == 0) {
//用管道的读端口 替换子进程的标准输入 即子进程冲管道读端口获取输入
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
execvp(argv2[0], argv2);
fprintf(stderr, "** bad command 2 : %m\n");
exit(1);
}
close(fd[0]);
close(fd[1]);
wait(&sv);
wait(&sv);
}
return 0;
}